rvar-0.3.0.2: Random Variables

Safe Haskell | Safe-Inferred
Language | Haskell2010

Data.RVar

Description

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 `RVar`s.

Synopsis

- type RVar = RVarT Identity
- runRVar :: StatefulGen g m => RVar a -> g -> m a
- sampleReaderRVar :: (StatefulGen g m, MonadReader g m) => RVar a -> m a
- sampleStateRVar :: (RandomGen g, MonadState g m) => RVar a -> m a
- pureRVar :: RandomGen g => RVar a -> g -> (a, g)
- data RVarT m a
- runRVarT :: StatefulGen g m => RVarT m a -> g -> m a
- sampleReaderRVarT :: (StatefulGen g m, MonadReader g m) => RVarT m a -> m a
- sampleStateRVarT :: (RandomGen g, MonadState g m) => RVarT m a -> m a
- runRVarTWith :: forall m n g a. StatefulGen g m => (forall t. n t -> m t) -> RVarT n a -> g -> m a
- sampleReaderRVarTWith :: forall m n a g. (StatefulGen g m, MonadReader g m) => (forall t. n t -> m t) -> RVarT n a -> m a
- sampleStateRVarTWith :: forall m n a g. (RandomGen g, MonadState g m) => (forall t. n t -> m t) -> RVarT n a -> m a
- data RGen = RGen
- uniformRVarT :: Uniform a => RVarT m a
- uniformRangeRVarT :: UniformRange a => (a, a) -> RVarT m a
- data Prim a where
  - PrimWord8 :: Prim Word8
  - PrimWord16 :: Prim Word16
  - PrimWord32 :: Prim Word32
  - PrimWord64 :: Prim Word64
  - PrimShortByteString :: !Int -> Prim ShortByteString

# Documentation

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:

- Using an immutable pseudo-random number generator that has an instance for `RandomGen` with `StateT` monad:

    >>> import qualified Data.Random as Fu (uniform)
    >>> import System.Random (mkStdGen)
    >>> import Control.Monad.State (runState)
    >>> runState (sampleStateRVar (Fu.uniform 1 (100 :: Integer))) (mkStdGen 2021)
    (79,StdGen {unStdGen = SMGen 4687568268719557181 4805600293067301895})

- Using a mutable pseud-random number generator that has an instance for `StatefulGen` with `ReaderT` monad.

    >>> import qualified Data.Random as Fu (uniform)
    >>> import System.Random.MWC (create)
    >>> import Control.Monad.Reader (runReaderT)
    >>> import qualified Data.Vector.Storable as VS
    >>> initialize (VS.singleton 2021) >>= runReaderT (sampleReaderRVar (uniform 1 (100 :: Integer)))
    8

runRVar :: StatefulGen g m => RVar a -> g -> m a Source #

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

sampleReaderRVar :: (StatefulGen g m, MonadReader g m) => RVar a -> m a Source #

`sampleRVar x` is equivalent to `runRVar x `StdRandom``.

sampleStateRVar :: (RandomGen g, MonadState g m) => RVar a -> m a Source #

pureRVar :: RandomGen g => RVar a -> g -> (a, g) Source #

Sample random variable using `RandomGen` generator as source of entropy

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, 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

Instances details

MonadTrans RVarT Source # |
Instance details Defined in Data.RVar Methods lift :: Monad m => m a -> RVarT m a Source #
MonadPrompt Prim (RVarT n) Source # |
Instance details Defined in Data.RVar Methods prompt :: Prim a -> RVarT n a Source #
StatefulGen RGen (RVarT m) Source # |

Instance details

Defined in Data.RVar

Methods

uniformWord32R :: Word32 -> RGen -> RVarT m Word32 Source #

uniformWord64R :: Word64 -> RGen -> RVarT m Word64 Source #

uniformWord8 :: RGen -> RVarT m Word8 Source #

uniformWord16 :: RGen -> RVarT m Word16 Source #

uniformWord32 :: RGen -> RVarT m Word32 Source #

uniformWord64 :: RGen -> RVarT m Word64 Source #

uniformShortByteString :: Int -> RGen -> RVarT m ShortByteString Source #

MonadIO m => MonadIO (RVarT m) Source # |
Instance details Defined in Data.RVar Methods liftIO :: IO a -> RVarT m a Source #
Applicative (RVarT n) Source # |
Instance details Defined in Data.RVar Methods pure :: a -> RVarT n a Source # (<*>) :: RVarT n (a -> b) -> RVarT n a -> RVarT n b Source # liftA2 :: (a -> b -> c) -> RVarT n a -> RVarT n b -> RVarT n c Source # (*>) :: RVarT n a -> RVarT n b -> RVarT n b Source # (<*) :: RVarT n a -> RVarT n b -> RVarT n a Source #
Functor (RVarT n) Source # |
Instance details Defined in Data.RVar Methods fmap :: (a -> b) -> RVarT n a -> RVarT n b Source # (<$) :: a -> RVarT n b -> RVarT n a Source #
Monad (RVarT n) Source # |
Instance details Defined in Data.RVar Methods (>>=) :: RVarT n a -> (a -> RVarT n b) -> RVarT n b Source # (>>) :: RVarT n a -> RVarT n b -> RVarT n b Source # return :: a -> RVarT n a Source #

runRVarT :: StatefulGen g m => RVarT m a -> g -> m a Source #

sampleReaderRVarT :: (StatefulGen g m, MonadReader g m) => RVarT m a -> m a Source #

sampleStateRVarT :: (RandomGen g, MonadState g m) => RVarT m a -> m a Source #

runRVarTWith :: forall m n g a. StatefulGen g m => (forall t. n t -> m t) -> RVarT n a -> g -> 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.

sampleReaderRVarTWith :: forall m n a g. (StatefulGen g m, MonadReader g m) => (forall t. n t -> m t) -> RVarT n a -> m a Source #

`sampleRVarTWith lift x` is equivalent to `runRVarTWith lift x `StdRandom``.

sampleStateRVarTWith :: forall m n a g. (RandomGen g, MonadState g m) => (forall t. n t -> m t) -> RVarT n a -> m a Source #

`sampleRVarTWith lift x` is equivalent to `runRVarTWith lift x `StdRandom``.

data RGen Source #

Constructors

RGen |

#### Instances

Instances details

StatefulGen RGen (RVarT m) Source # |

Instance details

Defined in Data.RVar

Methods

uniformWord32R :: Word32 -> RGen -> RVarT m Word32 Source #

uniformWord64R :: Word64 -> RGen -> RVarT m Word64 Source #

uniformWord8 :: RGen -> RVarT m Word8 Source #

uniformWord16 :: RGen -> RVarT m Word16 Source #

uniformWord32 :: RGen -> RVarT m Word32 Source #

uniformWord64 :: RGen -> RVarT m Word64 Source #

uniformShortByteString :: Int -> RGen -> RVarT m ShortByteString Source #

uniformRVarT :: Uniform a => RVarT m a Source #

uniformRangeRVarT :: UniformRange a => (a, a) -> RVarT m a Source #

data Prim a where Source #

A `Prompt` GADT describing a request for a primitive random variate. Random variable definitions will request their entropy via these prompts, and entropy sources will satisfy those requests. This data type is needed for creating `StatefulGen` instance for `RVarT`

Constructors

PrimWord8 :: Prim Word8 | An unsigned byte, uniformly distributed from 0 to 0xff
PrimWord16 :: Prim Word16 | An unsigned 16-bit word, uniformly distributed from 0 to 0xffff
PrimWord32 :: Prim Word32 | An unsigned 32-bit word, uniformly distributed from 0 to 0xffffffff
PrimWord64 :: Prim Word64 | An unsigned 64-bit word, uniformly distributed from 0 to 0xffffffffffffffff
PrimShortByteString :: !Int -> Prim ShortByteString | A uniformly distributed `ShortByteString` of length `n` bytes

#### Instances

Instances details

MonadPrompt Prim (RVarT n) Source # |
Instance details Defined in Data.RVar Methods prompt :: Prim a -> RVarT n a Source #
Show (Prim a) Source # |
Instance details Defined in Data.RVar.Prim Methods showsPrec :: Int -> Prim a -> ShowS Source # show :: Prim a -> String Source # showList :: [Prim a] -> ShowS Source #