This module provides functions useful for implementing new `MonadRandom`

and `RandomSource`

instances for state-abstractions containing `PureMT`

values (the pure pseudorandom generator provided by the
mersenne-random-pure64 package), as well as instances for some common
cases.

A `PureMT`

generator is immutable, so `PureMT`

by itself cannot be a
`RandomSource`

(if it were, it would always give the same "random"
values). Some form of mutable state must be used, such as an `IORef`

,
`State`

monad, etc.. A few default instances are provided by this module
along with more-general functions (`getRandomPrimFromMTRef`

and
`getRandomPrimFromMTState`

) usable as implementations for new cases
users might need.

# Documentation

data PureMT

`PureMT`

, a pure mersenne twister pseudo-random number generator

Show PureMT | |

RandomGen PureMT | |

(Monad m, ModifyRef (IORef PureMT) m PureMT) => RandomSource m (IORef PureMT) | |

(Monad m, ModifyRef (STRef s PureMT) m PureMT) => RandomSource m (STRef s PureMT) | |

(Monad m1, ModifyRef (Ref m2 PureMT) m1 PureMT) => RandomSource m1 (Ref m2 PureMT) | |

Monad m => MonadRandom (StateT PureMT m) | |

Monad m => MonadRandom (StateT PureMT m) |

getRandomPrimBy :: Monad m => (forall t. (PureMT -> (t, PureMT)) -> m t) -> Prim a -> m aSource

Given a function for applying a `PureMT`

transformation to some hidden
state, this function derives a function able to generate all `Prim`

s
in the given monad. This is then suitable for either a `MonadRandom`

or
`RandomSource`

instance, where the `supportedPrims`

or
`supportedPrimsFrom`

function (respectively) is `const True`

.

getRandomPrimFromMTRef :: (Monad m, ModifyRef sr m PureMT) => sr -> Prim a -> m aSource

Given a mutable reference to a `PureMT`

generator, we can implement
`RandomSource`

for in any monad in which the reference can be modified.

Typically this would be used to define a new `RandomSource`

instance for
some new reference type or new monad in which an existing reference type
can be modified atomically. As an example, the following instance could
be used to describe how `IORef`

`PureMT`

can be a `RandomSource`

in the
`IO`

monad:

instance RandomSource IO (IORef PureMT) where supportedPrimsFrom _ _ = True getSupportedRandomPrimFrom = getRandomPrimFromMTRef

(note that there is actually a more general instance declared already covering this as a a special case, so there's no need to repeat this declaration anywhere)

Example usage:

main = do src <- newIORef (pureMT 1234) -- OR: newPureMT >>= newIORef x <- sampleFrom src (uniform 0 100) -- OR: runRVar (uniform 0 100) src print x

getRandomPrimFromMTState :: MonadState PureMT m => Prim a -> m aSource

Similarly, `getRandomPrimFromMTState x`

can be used in any "state"
monad in the mtl sense whose state is a `PureMT`

generator.
Additionally, the standard mtl state monads have `MonadRandom`

instances
which do precisely that, allowing an easy conversion of `RVar`

s and
other `Distribution`

instances to "pure" random variables (e.g., by
`runState . sample :: Distribution d t => d t -> PureMT -> (t, PureMT)`

.
`PureMT`

in the type there can be replaced by `StdGen`

or anything else
satisfying `MonadRandom (State s) => s`

).

For example, this module includes the following declaration:

instance MonadRandom (State PureMT) where supportedPrims _ _ = True getSupportedRandomPrim = getRandomPrimFromMTState

This describes a "standard" way of getting random values in `State`

`PureMT`

, which can then be used in various ways, for example (assuming
some `RVar`

`foo`

and some `Word64`

`seed`

):

runState (runRVar foo StdRandom) (pureMT seed) runState (sampleFrom StdRandom foo) (pureMT seed) runState (sample foo) (pureMT seed)

Of course, the initial `PureMT`

state could also be obtained by any other
convenient means, such as `newPureMT`

if you don't care what seed is used.