:9      LA random variable with access to operations in an underlying monad. Useful W examples include any form of state for implementing random processes with hysteresis, F or writer monads for implementing tracing of complicated algorithms. ;For example, a simple random walk can be implemented as an   value:  ! rwalkIO :: IO (RVarT IO Double)  rwalkIO d = do  lastVal <- newIORef 0   let x = do 1 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  ... IThe 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: 8 rwalk :: Int -> Double -> StdGen -> ([Double], StdGen)  rwalk count start gen =  flip evalState start .  flip runStateT gen . ( sampleRVarTWith MTL.lift $ - replicateM count rwalkState  An opaque type modeling a "random variable" - a value 5 which depends on the outcome of some random event.  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  s:  In a monad, using a :  - runRVar (uniform 1 100) DevRandom :: IO Int  In a monad, using a  instance:  0 sampleRVar (uniform 1 100) :: State PureMT Int 3 As a pure function transforming a functional RNG:  8 sampleState (uniform 1 100) :: StdGen -> (Int, StdGen) (where #sampleState = runState . sampleRVar) "Run" an  1 - samples the random variable from the provided  source of entropy.  sampleRVar x is equivalent to  runRVar x  StdRandom. "Runs" an +, sampling the random variable it defines. HThe 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) EOne example of a useful non-standard lifting would be one that takes  State sA to another monad with a different state representation (such as  IO with the state mapped to an IORef):  C 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   would have K to either be given access to the full capability of the monad in which it I will eventually be sampled (which, incidentally, would also have to be  monomorphic so you couldn' t sample one   in more than one monad)  or functions manipulating  #s would have to use higher-ranked ? types to enforce the same kind of isolation and polymorphism. sampleRVarTWith lift x is equivalent to runRVarTWith lift x  StdRandom.           rvar-0.2 Data.RVarrandom-source-0.3.0.2Data.Random.Internal.SourcegetRandomNByteIntegergetRandomDoublegetRandomWord64getRandomWord32getRandomWord16getRandomWord8 MonadRandom RandomSourceRVarTRVarrunRVar sampleRVarrunRVarT sampleRVarT runRVarTWithsampleRVarTWithghc-prim GHC.TypesIOunRVarT