-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Random Variables -- -- Random number generation based on modeling random variables by an -- abstract type (RVar) which can be composed and manipulated -- monadically and sampled in either monadic or "pure" styles. The -- primary purpose of this library is to support defining and sampling a -- wide variety of high quality random variables. Quality is prioritized -- over speed, but performance is an important goal too. In my testing, I -- have found it capable of speed comparable to other Haskell libraries, -- but still a fair bit slower than straight C implementations of the -- same algorithms. @package rvar @version 0.2 -- | Random variables. An RVar is a sampleable random variable. -- Because probability distributions form a monad, they are quite easy to -- work with in the standard Haskell monadic styles. For examples, see -- the source for any of the Distribution instances - they all -- are defined in terms of RVars. module Data.RVar -- | 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... -}
-- |])
--
class Monad m => RandomSource m :: (* -> *) s
-- | 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... -}
-- |])
--
class Monad m => MonadRandom m :: (* -> *)
getRandomWord8 :: MonadRandom m => m Word8
getRandomWord16 :: MonadRandom m => m Word16
getRandomWord32 :: MonadRandom m => m Word32
getRandomWord64 :: MonadRandom m => m Word64
getRandomDouble :: MonadRandom m => m Double
getRandomNByteInteger :: MonadRandom m => Int -> m Integer
-- | 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 several ways to sample -- RVars: -- --
-- runRVar (uniform 1 100) DevRandom :: IO Int ---- --
-- sampleRVar (uniform 1 100) :: State PureMT Int ---- --
-- sampleState (uniform 1 100) :: StdGen -> (Int, StdGen) ---- -- (where sampleState = runState . sampleRVar) type RVar = RVarT Identity -- | "Run" an RVar - samples the random variable from the provided -- source of entropy. runRVar :: RandomSource m s => RVar a -> s -> m a -- | sampleRVar x is equivalent to runRVar x -- StdRandom. sampleRVar :: MonadRandom m => RVar a -> m a -- | 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 --data RVarT m a runRVarT :: RandomSource m s => RVarT m a -> s -> m a sampleRVarT :: MonadRandom m => RVarT m a -> m a -- | "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 -- RVars would have to use higher-ranked types to enforce the same -- kind of isolation and polymorphism. runRVarTWith :: RandomSource m s => (forall t. n t -> m t) -> RVarT n a -> s -> m a -- | sampleRVarTWith lift x is equivalent to runRVarTWith lift -- x StdRandom. sampleRVarTWith :: MonadRandom m => (forall t. n t -> m t) -> RVarT n a -> m a instance MonadIO m => MonadIO (RVarT m) instance MonadTrans RVarT instance MonadPrompt Prim (RVarT n) instance Applicative (RVarT n) instance MonadRandom (RVarT n) instance Monad (RVarT n) instance Functor (RVarT n)