{-
 -      ``Data/Random/Distribution''
 -}
{-# LANGUAGE
    MultiParamTypeClasses, FlexibleContexts
  #-}

module Data.Random.Distribution where

import Data.Random.Lift
import Data.Random.RVar

-- |A definition of a random variable's distribution.  From the distribution
-- an 'RVar' can be created, or the distribution can be directly sampled using 
-- 'sampleFrom' or 'sample'.
class Distribution d t where
    -- |Return a random variable with this distribution.
    rvar :: d t -> RVar t
    rvar = rvarT

class Distribution d t => CDF d t where
    -- |Return the cumulative distribution function of this distribution.
    -- That is, a function taking @x :: t@ to the probability that the next
    -- sample will return a value less than or equal to x, according to some
    -- order or partial order (not necessarily an obvious one).
    --
    -- In the case where 't' is an instance of Ord, 'cdf' should correspond
    -- to the CDF with respect to that order.
    -- 
    -- In other cases, 'cdf' is only required to satisfy the following law:
    -- @fmap (cdf d) (rvar d)@
    -- must be uniformly distributed over (0,1).  Inclusion of either endpoint is optional,
    -- though the preferred range is (0,1].
    -- 
    -- Thus, 'cdf' for a product type should not be a joint CDF as commonly 
    -- defined, as that definition violates both conditions.
    -- Instead, it should be a univariate CDF over the product type.
    cdf :: d t -> t -> Double

-- |Return a random variable with the given distribution, pre-lifted to an arbitrary 'RVarT'.
-- Any arbitrary 'RVar' can also be converted to an 'RVarT m' for an arbitrary 'm', using
-- either 'lift' or 'sample'.
rvarT :: Distribution d t => d t -> RVarT n t
rvarT d = lift (rvar d)