Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- class Monad m => RandomSource (m :: Type -> Type) s
- class Monad m => MonadRandom (m :: Type -> Type) where
- getRandomWord8 :: m Word8
- getRandomWord16 :: m Word16
- getRandomWord32 :: m Word32
- getRandomWord64 :: m Word64
- getRandomDouble :: m Double
- getRandomNByteInteger :: Int -> m Integer
- type RVar = RVarT Identity
- runRVar :: RandomSource m s => RVar a -> s -> m a
- sampleRVar :: MonadRandom m => RVar a -> m a
- data RVarT m a
- runRVarT :: RandomSource m s => RVarT m a -> s -> m a
- sampleRVarT :: MonadRandom m => RVarT m a -> m a
- runRVarTWith :: forall m n s a. RandomSource m s => (forall t. n t -> m t) -> RVarT n a -> s -> m a
- sampleRVarTWith :: forall m n a. MonadRandom m => (forall t. n t -> m t) -> RVarT n a -> m a
Documentation
class Monad m => RandomSource (m :: Type -> Type) s #
A source of entropy which can be used in the given monad.
See also MonadRandom
.
Minimum implementation is either the internal getRandomPrimFrom
or all
other functions. Additionally, this class's interface is subject to
extension at any time, so it is very, very strongly recommended that
the randomSource
Template Haskell function be used to implement this
function rather than directly implementing it. That function takes care
of choosing default implementations for any missing functions; as long as
at least one function is implemented, it will derive sensible
implementations of all others.
To use randomSource
, just wrap your instance declaration as follows (and
enable the TemplateHaskell, MultiParamTypeClasses and GADTs language
extensions, as well as any others required by your instances, such as
FlexibleInstances):
$(randomSource [d| instance RandomSource FooM Bar where {- at least one RandomSource function... -} |])
Instances
Monad m => RandomSource m (GetPrim m) | |
Defined in Data.Random.Internal.Source getRandomPrimFrom :: GetPrim m -> Prim t -> m t # getRandomWord8From :: GetPrim m -> m Word8 # getRandomWord16From :: GetPrim m -> m Word16 # getRandomWord32From :: GetPrim m -> m Word32 # getRandomWord64From :: GetPrim m -> m Word64 # getRandomDoubleFrom :: GetPrim m -> m Double # getRandomNByteIntegerFrom :: GetPrim m -> Int -> m Integer # |
class Monad m => MonadRandom (m :: Type -> Type) where #
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.
Minimum implementation is either the internal getRandomPrim
or all
other functions. Additionally, this class's interface is subject to
extension at any time, so it is very, very strongly recommended that
the monadRandom
Template Haskell function be used to implement this
function rather than directly implementing it. That function takes care
of choosing default implementations for any missing functions; as long as
at least one function is implemented, it will derive sensible
implementations of all others.
To use monadRandom
, just wrap your instance declaration as follows (and
enable the TemplateHaskell and GADTs language extensions):
$(monadRandom [d| instance MonadRandom FooM where getRandomDouble = return pi getRandomWord16 = return 4 {- etc... -} |])
Nothing
getRandomWord8 :: m Word8 #
Generate a uniformly distributed random Word8
getRandomWord16 :: m Word16 #
Generate a uniformly distributed random Word16
getRandomWord32 :: m Word32 #
Generate a uniformly distributed random Word32
getRandomWord64 :: m Word64 #
Generate a uniformly distributed random Word64
getRandomDouble :: m Double #
Generate a uniformly distributed random Double
in the range 0 <= U < 1
getRandomNByteInteger :: Int -> m Integer #
Generate a uniformly distributed random Integer
in the range 0 <= U < 256^n
Instances
MonadRandom (RVarT n) Source # | |
Defined in Data.RVar getRandomPrim :: Prim t -> RVarT n t # getRandomWord8 :: RVarT n Word8 # getRandomWord16 :: RVarT n Word16 # getRandomWord32 :: RVarT n Word32 # getRandomWord64 :: RVarT n Word64 # getRandomDouble :: RVarT n Double # getRandomNByteInteger :: Int -> RVarT n Integer # |
type RVar = RVarT Identity Source #
An opaque type modeling a "random variable" - a value
which depends on the outcome of some random event. RVar
s
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 several ways to sample RVar
s:
- In a monad, using a
RandomSource
:
runRVar (uniform 1 100) DevRandom :: IO Int
- In a monad, using a
MonadRandom
instance:
sampleRVar (uniform 1 100) :: State PureMT Int
- As a pure function transforming a functional RNG:
sampleState (uniform 1 100) :: StdGen -> (Int, StdGen)
(where sampleState = runState . sampleRVar
)
runRVar :: RandomSource m s => RVar a -> s -> m a Source #
"Run" an RVar
- samples the random variable from the provided
source of entropy.
sampleRVar :: MonadRandom m => RVar a -> m a Source #
sampleRVar x
is equivalent to runRVar x
.StdRandom
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, after which it can be sampled as usual:
do rw <- rwalkIO x <- sampleRVarT rw y <- sampleRVarT 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:
rwalk :: Int -> Double -> StdGen -> ([Double], StdGen) rwalk count start gen = flip evalState start . flip runStateT gen . sampleRVarTWith MTL.lift $ replicateM count rwalkState
Instances
MonadTrans RVarT Source # | |
MonadPrompt Prim (RVarT n) Source # | |
Monad (RVarT n) Source # | |
Functor (RVarT n) Source # | |
Applicative (RVarT n) Source # | |
MonadIO m => MonadIO (RVarT m) Source # | |
MonadRandom (RVarT n) Source # | |
Defined in Data.RVar getRandomPrim :: Prim t -> RVarT n t # getRandomWord8 :: RVarT n Word8 # getRandomWord16 :: RVarT n Word16 # getRandomWord32 :: RVarT n Word32 # getRandomWord64 :: RVarT n Word64 # getRandomDouble :: RVarT n Double # getRandomNByteInteger :: Int -> RVarT n Integer # |
runRVarT :: RandomSource m s => RVarT m a -> s -> m a Source #
sampleRVarT :: MonadRandom m => RVarT m a -> m a Source #
runRVarTWith :: forall m n s a. RandomSource m s => (forall t. n t -> m t) -> RVarT n a -> s -> m a Source #
"Runs" an RVarT
, sampling the random variable it defines.
The first argument lifts the base monad into the sampling monad. 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
The ability to lift 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 RVar
s would have to use higher-ranked
types to enforce the same kind of isolation and polymorphism.
sampleRVarTWith :: forall m n a. MonadRandom m => (forall t. n t -> m t) -> RVarT n a -> m a Source #
sampleRVarTWith lift x
is equivalent to runRVarTWith lift x
.StdRandom