random-fu-0.1.0.0: Random number generation

Data.Random

Contents

Description

Flexible modeling and sampling of random variables.

The central abstraction in this library is the concept of a random variable. It is not fully formalized in the standard measure-theoretic language, but rather is informally defined as a "thing you can get random values out of". Different random variables may have different types of values they can return or the same types but different probabilities for each value they can return. The random values you get out of them are traditionally called "random variates".

Most imperative-language random number libraries are all about obtaining and manipulating random variates. This one is about defining, manipulating and sampling random variables. Computationally, the distinction is small and mostly just a matter of perspective, but from a program design perspective it provides both a powerfully composable abstraction and a very useful separation of concerns.

Abstract random variables as implemented by RVar are composable. They can be defined in a monadic / "imperative" style that amounts to manipulating variates, but with strict type-level isolation. Concrete random variables are also provided, but they do not compose as generically. The Distribution type class allows concrete random variables to "forget" their concreteness so that they can be composed. For examples of both, see the documentation for RVar and Distribution, as well as the code for any of the concrete distributions such as Uniform, Gamma, etc.

Both abstract and concrete random variables can be sampled (despite the types GHCi may list for the functions) by the functions in Data.Random.Sample.

Random variable sampling is done with regard to a generic basis of primitive random variables defined in Data.Random.Internal.Primitives. This basis is very low-level and the actual set of primitives is still fairly experimental, which is why it is in the "Internal" sub-heirarchy. User-defined variables should use the existing high-level variables such as Uniform and Normal rather than these basis variables. Data.Random.Source defines classes for entropy sources that provide implementations of these primitive variables. Several implementations are available in the Data.Random.Source.* modules.

Synopsis

Random variables

Abstract (RVar)

type RVar = RVarT IdentitySource

An opaque type modeling a "random variable" - a value which depends on the outcome of some random event. RVars can be conveniently defined by an imperative-looking style:

 normalPair =  do
     u <- stdUniform
     t <- stdUniform
     let r = sqrt (-2 * log u)
         theta = (2 * pi) * t
         
         x = r * cos theta
         y = r * sin theta
     return (x,y)

OR by a more applicative style:

 logNormal = exp <$> stdNormal

Once defined (in any style), there are a couple ways to sample RVars:

 sampleFrom DevRandom (uniform 1 100) :: IO Int
  • As a pure function transforming a functional RNG:
 sampleState (uniform 1 100) :: StdGen -> (Int, StdGen)

data RVarT m a Source

A random variable with access to operations in an underlying monad. Useful examples include any form of state for implementing random processes with hysteresis, or writer monads for implementing tracing of complicated algorithms.

For example, a simple random walk can be implemented as an RVarT IO value:

 rwalkIO :: IO (RVarT IO Double)
 rwalkIO d = do
     lastVal <- newIORef 0
     
     let x = do
             prev    <- lift (readIORef lastVal)
             change  <- rvarT StdNormal
             
             let new = prev + change
             lift (writeIORef lastVal new)
             return new
         
     return x

To run the random walk, it must first be initialized, and then it can be sampled as usual:

 do
     rw <- rwalkIO
     x <- sampleFrom DevURandom rw
     y <- sampleFrom DevURandom rw
     ...

The same random-walk process as above can be implemented using MTL types as follows (using import Control.Monad.Trans as MTL):

 rwalkState :: RVarT (State Double) Double
 rwalkState = do
     prev <- MTL.lift get
     change  <- rvarT StdNormal
     
     let new = prev + change
     MTL.lift (put new)
     return new

Invocation is straightforward (although a bit noisy) if you're used to MTL, but there is a gotcha lurking here: sample and runRVarT inherit the extreme generality of lift, so there will almost always need to be an explicit type signature lurking somewhere in any client code making use of RVarT with MTL types. In this example, the inferred type of start would be too general to be practical, so the signature for rwalk explicitly fixes it to Double. Alternatively, in this case sample could be replaced with \x -> runRVarTWith MTL.lift x StdRandom.

 rwalk :: Int -> Double -> StdGen -> ([Double], StdGen)
 rwalk count start gen = evalState (runStateT (sample (replicateM count rwalkState)) gen) start

runRVar :: RandomSource m s => RVar a -> s -> m aSource

"Run" an RVar - samples the random variable from the provided source of entropy.

runRVarT :: (Lift n m, RandomSource m s) => RVarT n a -> s -> m aSource

"Runs" an RVarT, sampling the random variable it defines.

The Lift context allows random variables to be defined using a minimal underlying functor (Identity is sufficient for "conventional" random variables) and then sampled in any monad into which the underlying functor can be embedded (which, for Identity, is all monads).

The lifting is very important - without it, every RVar would have to either be given access to the full capability of the monad in which it will eventually be sampled (which, incidentally, would also have to be monomorphic so you couldn't sample one RVar in more than one monad) or functions manipulating RVars would have to use higher-ranked types to enforce the same kind of isolation and polymorphism.

For non-standard liftings or those where you would rather not introduce a Lift instance, see runRVarTWith.

runRVarTWith :: RandomSource m s => (forall t. n t -> m t) -> RVarT n a -> s -> m aSource

Like runRVarT but allowing a user-specified lift operation. This operation must obey the "monad transformer" laws:

 lift . return = return
 lift (x >>= f) = (lift x) >>= (lift . f)

One example of a useful non-standard lifting would be one that takes State s to another monad with a different state representation (such as IO with the state mapped to an IORef):

 embedState :: (Monad m) => m s -> (s -> m ()) -> State s a -> m a
 embedState get put = \m -> do
     s <- get
     (res,s) <- return (runState m s)
     put s
     return res

Concrete (Distribution)

class Distribution d t whereSource

A Distribution is a data representation of a random variable's probability structure. For example, in Data.Random.Distribution.Normal, the Normal distribution is defined as:

 data Normal a
     = StdNormal
     | Normal a a

Where the two parameters of the Normal data constructor are the mean and standard deviation of the random variable, respectively. To make use of the Normal type, one can convert it to an rvar and manipulate it or sample it directly:

 x <- sample (rvar (Normal 10 2))
 x <- sample (Normal 10 2)

A Distribution is typically more transparent than an RVar but less composable (precisely because of that transparency). There are several practical uses for types implementing Distribution:

  • Typically, a Distribution will expose several parameters of a standard mathematical model of a probability distribution, such as mean and std deviation for the normal distribution. Thus, they can be manipulated analytically using mathematical insights about the distributions they represent. For example, a collection of bernoulli variables could be simplified into a (hopefully) smaller collection of binomial variables.
  • Because they are generally just containers for parameters, they can be easily serialized to persistent storage or read from user-supplied configurations (eg, initialization data for a simulation).
  • If a type additionally implements the CDF subclass, which extends Distribution with a cumulative density function, an arbitrary random variable x can be tested against the distribution by testing fmap (cdf dist) x for uniformity.

On the other hand, most Distributions will not be closed under all the same operations as RVar (which, being a monad, has a fully turing-complete internal computational model). The sum of two uniformly-distributed variables, for example, is not uniformly distributed. To support general composition, the Distribution class defines a function rvar to construct the more-abstract and more-composable RVar representation of a random variable.

Methods

rvar :: d t -> RVar tSource

Return a random variable with this distribution.

rvarT :: d t -> RVarT n tSource

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.

Instances

Distribution StdUniform Bool 
Distribution StdUniform Char 
Distribution StdUniform Double 
Distribution StdUniform Float 
Distribution StdUniform Int 
Distribution StdUniform Int8 
Distribution StdUniform Int16 
Distribution StdUniform Int32 
Distribution StdUniform Int64 
Distribution StdUniform Ordering 
Distribution StdUniform Word 
Distribution StdUniform Word8 
Distribution StdUniform Word16 
Distribution StdUniform Word32 
Distribution StdUniform Word64 
Distribution StdUniform () 
Distribution Uniform Bool 
Distribution Uniform Char 
Distribution Uniform Double 
Distribution Uniform Float 
Distribution Uniform Int 
Distribution Uniform Int8 
Distribution Uniform Int16 
Distribution Uniform Int32 
Distribution Uniform Int64 
Distribution Uniform Integer 
Distribution Uniform Ordering 
Distribution Uniform Word 
Distribution Uniform Word8 
Distribution Uniform Word16 
Distribution Uniform Word32 
Distribution Uniform Word64 
Distribution Uniform () 
(Floating a, Distribution StdUniform a) => Distribution Weibull a 
(Floating a, Distribution StdUniform a) => Distribution Exponential a 
Distribution Normal Double 
Distribution Normal Float 
(Floating a, Ord a, Distribution Normal a, Distribution StdUniform a) => Distribution Gamma a 
Distribution Beta Double 
Distribution Beta Float 
(RealFloat a, Distribution StdUniform a) => Distribution Rayleigh a 
(RealFloat a, Ord a, Distribution StdUniform a) => Distribution Triangular a 
HasResolution r => Distribution StdUniform (Fixed r) 
HasResolution r => Distribution Uniform (Fixed r) 
(Fractional a, Distribution Gamma a) => Distribution Dirichlet [a] 
(Fractional b, Ord b, Distribution StdUniform b) => Distribution (Bernoulli b) Bool 
Distribution (Bernoulli b[a137h]) Bool => Distribution (Bernoulli b[a137h]) Word64 
Distribution (Bernoulli b[a137d]) Bool => Distribution (Bernoulli b[a137d]) Word32 
Distribution (Bernoulli b[a1379]) Bool => Distribution (Bernoulli b[a1379]) Word16 
Distribution (Bernoulli b[a1375]) Bool => Distribution (Bernoulli b[a1375]) Word8 
Distribution (Bernoulli b[a1371]) Bool => Distribution (Bernoulli b[a1371]) Word 
Distribution (Bernoulli b[a136X]) Bool => Distribution (Bernoulli b[a136X]) Int64 
Distribution (Bernoulli b[a136T]) Bool => Distribution (Bernoulli b[a136T]) Int32 
Distribution (Bernoulli b[a136P]) Bool => Distribution (Bernoulli b[a136P]) Int16 
Distribution (Bernoulli b[a136L]) Bool => Distribution (Bernoulli b[a136L]) Int8 
Distribution (Bernoulli b[a136H]) Bool => Distribution (Bernoulli b[a136H]) Int 
Distribution (Bernoulli b[a136A]) Bool => Distribution (Bernoulli b[a136A]) Integer 
Distribution (Bernoulli b[a13ou]) Bool => Distribution (Bernoulli b[a13ou]) Double 
Distribution (Bernoulli b[a13oq]) Bool => Distribution (Bernoulli b[a13oq]) Float 
(Fractional p, Ord p, Distribution StdUniform p) => Distribution (Categorical p) a 
(Num t, Ord t, Vector v t) => Distribution (Ziggurat v) t 
(Integral a, Floating b, Ord b, Distribution Normal b, Distribution StdUniform b) => Distribution (Erlang a) b 
(Floating b[a1n1b], Ord b[a1n1b], Distribution Beta b[a1n1b], Distribution StdUniform b[a1n1b]) => Distribution (Binomial b[a1n1b]) Word64 
(Floating b[a1n15], Ord b[a1n15], Distribution Beta b[a1n15], Distribution StdUniform b[a1n15]) => Distribution (Binomial b[a1n15]) Word32 
(Floating b[a1n0Z], Ord b[a1n0Z], Distribution Beta b[a1n0Z], Distribution StdUniform b[a1n0Z]) => Distribution (Binomial b[a1n0Z]) Word16 
(Floating b[a1n0T], Ord b[a1n0T], Distribution Beta b[a1n0T], Distribution StdUniform b[a1n0T]) => Distribution (Binomial b[a1n0T]) Word8 
(Floating b[a1n0N], Ord b[a1n0N], Distribution Beta b[a1n0N], Distribution StdUniform b[a1n0N]) => Distribution (Binomial b[a1n0N]) Word 
(Floating b[a1n0H], Ord b[a1n0H], Distribution Beta b[a1n0H], Distribution StdUniform b[a1n0H]) => Distribution (Binomial b[a1n0H]) Int64 
(Floating b[a1n0B], Ord b[a1n0B], Distribution Beta b[a1n0B], Distribution StdUniform b[a1n0B]) => Distribution (Binomial b[a1n0B]) Int32 
(Floating b[a1n0v], Ord b[a1n0v], Distribution Beta b[a1n0v], Distribution StdUniform b[a1n0v]) => Distribution (Binomial b[a1n0v]) Int16 
(Floating b[a1n0p], Ord b[a1n0p], Distribution Beta b[a1n0p], Distribution StdUniform b[a1n0p]) => Distribution (Binomial b[a1n0p]) Int8 
(Floating b[a1n0j], Ord b[a1n0j], Distribution Beta b[a1n0j], Distribution StdUniform b[a1n0j]) => Distribution (Binomial b[a1n0j]) Int 
(Floating b[a1n0d], Ord b[a1n0d], Distribution Beta b[a1n0d], Distribution StdUniform b[a1n0d]) => Distribution (Binomial b[a1n0d]) Integer 
Distribution (Binomial b[a1nlK]) Integer => Distribution (Binomial b[a1nlK]) Double 
Distribution (Binomial b[a1nlE]) Integer => Distribution (Binomial b[a1nlE]) Float 
(RealFloat b[a1soP], Distribution StdUniform b[a1soP], Distribution (Erlang Word64) b[a1soP], Distribution (Binomial b[a1soP]) Word64) => Distribution (Poisson b[a1soP]) Word64 
(RealFloat b[a1soL], Distribution StdUniform b[a1soL], Distribution (Erlang Word32) b[a1soL], Distribution (Binomial b[a1soL]) Word32) => Distribution (Poisson b[a1soL]) Word32 
(RealFloat b[a1soH], Distribution StdUniform b[a1soH], Distribution (Erlang Word16) b[a1soH], Distribution (Binomial b[a1soH]) Word16) => Distribution (Poisson b[a1soH]) Word16 
(RealFloat b[a1soD], Distribution StdUniform b[a1soD], Distribution (Erlang Word8) b[a1soD], Distribution (Binomial b[a1soD]) Word8) => Distribution (Poisson b[a1soD]) Word8 
(RealFloat b[a1soz], Distribution StdUniform b[a1soz], Distribution (Erlang Word) b[a1soz], Distribution (Binomial b[a1soz]) Word) => Distribution (Poisson b[a1soz]) Word 
(RealFloat b[a1sov], Distribution StdUniform b[a1sov], Distribution (Erlang Int64) b[a1sov], Distribution (Binomial b[a1sov]) Int64) => Distribution (Poisson b[a1sov]) Int64 
(RealFloat b[a1sor], Distribution StdUniform b[a1sor], Distribution (Erlang Int32) b[a1sor], Distribution (Binomial b[a1sor]) Int32) => Distribution (Poisson b[a1sor]) Int32 
(RealFloat b[a1son], Distribution StdUniform b[a1son], Distribution (Erlang Int16) b[a1son], Distribution (Binomial b[a1son]) Int16) => Distribution (Poisson b[a1son]) Int16 
(RealFloat b[a1soj], Distribution StdUniform b[a1soj], Distribution (Erlang Int8) b[a1soj], Distribution (Binomial b[a1soj]) Int8) => Distribution (Poisson b[a1soj]) Int8 
(RealFloat b[a1sof], Distribution StdUniform b[a1sof], Distribution (Erlang Int) b[a1sof], Distribution (Binomial b[a1sof]) Int) => Distribution (Poisson b[a1sof]) Int 
(RealFloat b[a1sob], Distribution StdUniform b[a1sob], Distribution (Erlang Integer) b[a1sob], Distribution (Binomial b[a1sob]) Integer) => Distribution (Poisson b[a1sob]) Integer 
Distribution (Poisson b[a1sPg]) Integer => Distribution (Poisson b[a1sPg]) Double 
Distribution (Poisson b[a1sPc]) Integer => Distribution (Poisson b[a1sPc]) Float 
(Distribution (Bernoulli b) Bool, RealFloat a) => Distribution (Bernoulli b) (Complex a) 
(Distribution (Bernoulli b) Bool, Integral a) => Distribution (Bernoulli b) (Ratio a) 
(Num a, Fractional p, Distribution (Binomial p) a) => Distribution (Multinomial p) [a] 

class Distribution d t => CDF d t whereSource

Methods

cdf :: d t -> t -> DoubleSource

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].

Note that this definition requires that 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. That is, it should represent the CDF with respect to the lexicographic order of the product.

The present specification is probably only really useful for testing conformance of a variable to its target distribution, and I am open to suggestions for more-useful specifications (especially with regard to the interaction with product types).

Instances

CDF StdUniform Bool 
CDF StdUniform Char 
CDF StdUniform Double 
CDF StdUniform Float 
CDF StdUniform Int 
CDF StdUniform Int8 
CDF StdUniform Int16 
CDF StdUniform Int32 
CDF StdUniform Int64 
CDF StdUniform Ordering 
CDF StdUniform Word 
CDF StdUniform Word8 
CDF StdUniform Word16 
CDF StdUniform Word32 
CDF StdUniform Word64 
CDF StdUniform () 
CDF Uniform Bool 
CDF Uniform Char 
CDF Uniform Double 
CDF Uniform Float 
CDF Uniform Int 
CDF Uniform Int8 
CDF Uniform Int16 
CDF Uniform Int32 
CDF Uniform Int64 
CDF Uniform Integer 
CDF Uniform Ordering 
CDF Uniform Word 
CDF Uniform Word8 
CDF Uniform Word16 
CDF Uniform Word32 
CDF Uniform Word64 
CDF Uniform () 
(Real a, Distribution Weibull a) => CDF Weibull a 
(Real a, Distribution Exponential a) => CDF Exponential a 
(Real a, Distribution Normal a) => CDF Normal a 
(Real a, Distribution Rayleigh a) => CDF Rayleigh a 
(RealFrac a, Distribution Triangular a) => CDF Triangular a 
HasResolution r => CDF StdUniform (Fixed r) 
HasResolution r => CDF Uniform (Fixed r) 
(Distribution (Bernoulli b) Bool, Real b) => CDF (Bernoulli b) Bool 
CDF (Bernoulli b[a137j]) Bool => CDF (Bernoulli b[a137j]) Word64 
CDF (Bernoulli b[a137f]) Bool => CDF (Bernoulli b[a137f]) Word32 
CDF (Bernoulli b[a137b]) Bool => CDF (Bernoulli b[a137b]) Word16 
CDF (Bernoulli b[a1377]) Bool => CDF (Bernoulli b[a1377]) Word8 
CDF (Bernoulli b[a1373]) Bool => CDF (Bernoulli b[a1373]) Word 
CDF (Bernoulli b[a136Z]) Bool => CDF (Bernoulli b[a136Z]) Int64 
CDF (Bernoulli b[a136V]) Bool => CDF (Bernoulli b[a136V]) Int32 
CDF (Bernoulli b[a136R]) Bool => CDF (Bernoulli b[a136R]) Int16 
CDF (Bernoulli b[a136N]) Bool => CDF (Bernoulli b[a136N]) Int8 
CDF (Bernoulli b[a136J]) Bool => CDF (Bernoulli b[a136J]) Int 
CDF (Bernoulli b[a136C]) Bool => CDF (Bernoulli b[a136C]) Integer 
CDF (Bernoulli b[a13ow]) Bool => CDF (Bernoulli b[a13ow]) Double 
CDF (Bernoulli b[a13os]) Bool => CDF (Bernoulli b[a13os]) Float 
(Real b[a1n1e], Distribution (Binomial b[a1n1e]) Word64) => CDF (Binomial b[a1n1e]) Word64 
(Real b[a1n18], Distribution (Binomial b[a1n18]) Word32) => CDF (Binomial b[a1n18]) Word32 
(Real b[a1n12], Distribution (Binomial b[a1n12]) Word16) => CDF (Binomial b[a1n12]) Word16 
(Real b[a1n0W], Distribution (Binomial b[a1n0W]) Word8) => CDF (Binomial b[a1n0W]) Word8 
(Real b[a1n0Q], Distribution (Binomial b[a1n0Q]) Word) => CDF (Binomial b[a1n0Q]) Word 
(Real b[a1n0K], Distribution (Binomial b[a1n0K]) Int64) => CDF (Binomial b[a1n0K]) Int64 
(Real b[a1n0E], Distribution (Binomial b[a1n0E]) Int32) => CDF (Binomial b[a1n0E]) Int32 
(Real b[a1n0y], Distribution (Binomial b[a1n0y]) Int16) => CDF (Binomial b[a1n0y]) Int16 
(Real b[a1n0s], Distribution (Binomial b[a1n0s]) Int8) => CDF (Binomial b[a1n0s]) Int8 
(Real b[a1n0m], Distribution (Binomial b[a1n0m]) Int) => CDF (Binomial b[a1n0m]) Int 
(Real b[a1n0g], Distribution (Binomial b[a1n0g]) Integer) => CDF (Binomial b[a1n0g]) Integer 
CDF (Binomial b[a1nlN]) Integer => CDF (Binomial b[a1nlN]) Double 
CDF (Binomial b[a1nlH]) Integer => CDF (Binomial b[a1nlH]) Float 
(Real b[a1soR], Distribution (Poisson b[a1soR]) Word64) => CDF (Poisson b[a1soR]) Word64 
(Real b[a1soN], Distribution (Poisson b[a1soN]) Word32) => CDF (Poisson b[a1soN]) Word32 
(Real b[a1soJ], Distribution (Poisson b[a1soJ]) Word16) => CDF (Poisson b[a1soJ]) Word16 
(Real b[a1soF], Distribution (Poisson b[a1soF]) Word8) => CDF (Poisson b[a1soF]) Word8 
(Real b[a1soB], Distribution (Poisson b[a1soB]) Word) => CDF (Poisson b[a1soB]) Word 
(Real b[a1sox], Distribution (Poisson b[a1sox]) Int64) => CDF (Poisson b[a1sox]) Int64 
(Real b[a1sot], Distribution (Poisson b[a1sot]) Int32) => CDF (Poisson b[a1sot]) Int32 
(Real b[a1sop], Distribution (Poisson b[a1sop]) Int16) => CDF (Poisson b[a1sop]) Int16 
(Real b[a1sol], Distribution (Poisson b[a1sol]) Int8) => CDF (Poisson b[a1sol]) Int8 
(Real b[a1soh], Distribution (Poisson b[a1soh]) Int) => CDF (Poisson b[a1soh]) Int 
(Real b[a1sod], Distribution (Poisson b[a1sod]) Integer) => CDF (Poisson b[a1sod]) Integer 
CDF (Poisson b[a1sPi]) Integer => CDF (Poisson b[a1sPi]) Double 
CDF (Poisson b[a1sPe]) Integer => CDF (Poisson b[a1sPe]) Float 
(CDF (Bernoulli b) Bool, RealFloat a) => CDF (Bernoulli b) (Complex a) 
(CDF (Bernoulli b) Bool, Integral a) => CDF (Bernoulli b) (Ratio a) 

Sampling random variables

class Sampleable d m t whereSource

A typeclass allowing Distributions and RVars to be sampled. Both may also be sampled via runRVar or runRVarT, but I find it psychologically pleasing to be able to sample both using this function, as they are two separate abstractions for one base concept: a random variable.

Methods

sampleFrom :: RandomSource m s => s -> d t -> m tSource

Directly sample from a distribution or random variable, using the given source of entropy.

Instances

Distribution d t => Sampleable d m t 
Lift m n => Sampleable (RVarT m) n t 

sample :: (Sampleable d m t, MonadRandom m) => d t -> m tSource

Sample a random variable using the default source of entropy for the monad in which the sampling occurs.

sampleState :: (Sampleable d (State s) t, MonadRandom (State s)) => d t -> s -> (t, s)Source

Sample a random variable in a "functional" style. Typical instantiations of s are System.Random.StdGen or System.Random.Mersenne.Pure64.PureMT.

sampleStateT :: (Sampleable d (StateT s m) t, MonadRandom (StateT s m)) => d t -> s -> m (t, s)Source

Sample a random variable in a "semi-functional" style. Typical instantiations of s are System.Random.StdGen or System.Random.Mersenne.Pure64.PureMT.

A few very common distributions

stdUniform :: Distribution StdUniform a => RVar aSource

Get a "standard" uniformly distributed value. For integral types, this means uniformly distributed over the full range of the type (there is no support for Integer). For fractional types, this means uniformly distributed on the interval [0,1).

data Normal a Source

A specification of a normal distribution over the type a.

Constructors

StdNormal

The "standard" normal distribution - mean 0, stddev 1

Normal a a

Normal m s is a normal distribution with mean m and stddev sd.

normal :: Distribution Normal a => a -> a -> RVar aSource

normal m s is a random variable with distribution Normal m s.

stdNormal :: Distribution Normal a => RVar aSource

stdNormal is a normal variable with distribution StdNormal.

data Gamma a Source

Constructors

Gamma a a 

gamma :: Distribution Gamma a => a -> a -> RVar aSource

Entropy Sources

class Monad m => MonadRandom m Source

A typeclass for monads with a chosen source of entropy. For example, RVar is such a monad - the source from which it is (eventually) sampled is the only source from which a random variable is permitted to draw, so when directly requesting entropy for a random variable these functions are used.

The minimal definition is supportedPrims and getSupportedRandomPrim with cases for those primitives where supportedPrims returns True.

It is recommended (despite the warnings it generates) that, even when all primitives are supported, a final wildcard case of supportedPrims is specified, as:

 supportedPrims _ _ = False

The overlapping pattern warnings can be suppressed (without suppressing other, genuine, overlapping-pattern warnings) by the GHC flag -fno-warn-simple-patterns. This is not actually the documented behavior of that flag as far as I can find in 3 google-minutes, but it works with GHC 6.12.1 anyway, and that's good enough for me.

Note that it is very important that at least supportedPrims (and preferably getSupportedRandomPrim as well) gets inlined into the default implementation of getRandomPrim. If your supportedPrims is more than about 2 or 3 cases, add an INLINE pragma so that it can be optimized out of getRandomPrim.

class Monad m => RandomSource m s Source

A source of entropy which can be used in the given monad.

The minimal definition is supportedPrimsFrom and getSupportedRandomPrimFrom with cases for those primitives where supportedPrimsFrom returns True.

Note that it is very important that at least supportedPrimsFrom (and preferably getSupportedRandomPrimFrom as well) gets inlined into the default implementation of getRandomPrimFrom. If your supportedPrimsFrom is more than about 2 or 3 cases, add an INLINE pragma so that it can be optimized out of getRandomPrimFrom.

See also MonadRandom.

data StdRandom Source

A token representing the "standard" entropy source in a MonadRandom monad. Its sole purpose is to make the following true (when the types check):

 sampleFrom StdRandom === sample

Constructors

StdRandom 

Useful list-based operations

randomElement :: [a] -> RVar aSource

A random variable returning an arbitrary element of the given list. Every element has equal probability of being chosen. Because it is a pure RVar it has no memory - that is, it "draws with replacement."

shuffle :: [a] -> RVar [a]Source

A random variable that returns the given list in an arbitrary shuffled order. Every ordering of the list has equal probability.

shuffleN :: Int -> [a] -> RVar [a]Source

A random variable that shuffles a list of a known length (or a list prefix of the specified length). Useful for shuffling large lists when the length is known in advance. Avoids needing to traverse the list to discover its length. Each ordering has equal probability.

shuffleNofM :: Int -> Int -> [a] -> RVar [a]Source

A random variable that selects N arbitrary elements of a list of known length M.