Stability experimental
 Contents Common interface Bayes' rule Random sampling functions Discrete, finite distributions
Description

Common interface for probability distribution monads. Heavily inspired by Martin Erwig's and Steve Kollmansberger's Probabilistic Functional Programming, which can be found at http://web.engr.oregonstate.edu/~erwig/pfp/.

For background, see Michele Giry, A Categorical Approach to Probability Theory.

Synopsis
class (Functor d, Monad d) => Dist d where
 weighted :: [(a, Rational)] -> d a
weighted :: Dist d => [(a, Rational)] -> d a
uniform :: Dist d => [a] -> d a
sample :: MonadRandom m => m a -> Int -> m [a]
sampleIO :: Rand StdGen a -> Int -> IO [a]
type BRand g = MaybeT (Rand g)
sampleBayes :: MonadRandom m => MaybeT m a -> Int -> m [a]
sampleBayesIO :: BRand StdGen a -> Int -> IO [a]
bayes :: Probability p => MaybeT (MVT p []) a -> Maybe (MVT p [] a)
Common interface

Common interfaces to probability monads. For example, if we assume that a family has two children, each a boy or a girl, we can build a probability distribution representing all such families.

```

data Child = Girl | Boy
deriving (Show, Eq, Ord)

child = uniform [Girl, Boy]

family = do
child1 <- child
child2 <- child
return [child1, child2]
```

The use of NoMonomorphismRestriction is optional. It eliminates the need for type declarations on child and family:

```child :: (Dist d) => d Child
child = uniform [Girl, Boy]

family :: (Dist d) => d [Child]
family = ...
```

Unfortunately, using NoMonomorphismRestriction may hide potential performance issues. In either of the above examples, Haskell compilers may recompute child from scratch each time it is called, because the actual type of the distribution d is unknown. Normally, Haskell requires an explicit type declaration in this case, in hope that you will notice the potential performance issue. By enabling NoMonomorphismRestriction, you indicate that you intended the code to work this way, and don't wish to use type declarations on every definition.

class (Functor d, Monad d) => Dist d where
Represents a probability distribution.
Methods
 weighted :: [(a, Rational)] -> d a Creates a new distribution from a weighted list of values. The individual weights must be non-negative, and they must sum to a positive number.
Instances
 Dist d => Dist (MaybeT d) RandomGen g => Dist (Rand g) Probability p => Dist (MVT p []) (Monad m, RandomGen g) => Dist (RandT g m)
weighted :: Dist d => [(a, Rational)] -> d a
Creates a new distribution from a weighted list of values. The individual weights must be non-negative, and they must sum to a positive number.
uniform :: Dist d => [a] -> d a
Creates a new distribution from a list of values, weighting it evenly.
Bayes' rule

Using guard, it's possible to calculate conditional probabilities using Bayes' rule. In the example below, we choose to Control.Monad.Distribution.Rational, which calculates probabilities using exact rational numbers. This is useful for small, interactive programs where you want answers like 13 and 23 instead of 0.3333333 and 0.6666666.

```
import Data.List

data Coin = Heads | Tails
deriving (Eq, Ord, Show)

tosses n = sequence (replicate n toss)

result <- tosses n
return result
```

In this example, we use guard to discard possible outcomes where no coin comes up heads.

Random sampling functions

Support for probability distributions represented by sampling functions. This API is heavily inspired by Sungwoo Park and colleagues' \$lambda_{bigcirc}\$ caculus http://citeseer.ist.psu.edu/752237.html.

Two sampling-function monads are available: Rand and BRand. The former provides ordinary sampling functions, and the latter supports Bayesian reasoning.

It's possible run code in the Rand monad using either sample or sampleIO.

```sampleIO family 3
-- [[Boy,Girl],[Boy,Girl],[Girl,Girl]]
```

If the probability distribution uses guard, you can run it using sampleBayesIO. Note that one of the outcomes below was discarded, leaving 3 outcomes instead of the expected 4:

```sampleBayesIO (tossesWithAtLeastOneHead 2) 4
```
sample :: MonadRandom m => m a -> Int -> m [a]
Take n samples from the distribution r.
sampleIO :: Rand StdGen a -> Int -> IO [a]
Take n samples from the distribution r using the IO monad.
type BRand g = MaybeT (Rand g)
A random distribution where some samples may be discarded.
sampleBayes :: MonadRandom m => MaybeT m a -> Int -> m [a]
Take n samples from the distribution r, and eliminate any samples which fail a guard condition.
sampleBayesIO :: BRand StdGen a -> Int -> IO [a]
Take n samples from the distribution r using the IO monad, and eliminate any samples which fail a guard condition.
Discrete, finite distributions

Using the DDist and BDDist monads, you can compute exact distributions. For example:

```ddist family
-- [MV 0.25 [Girl,Girl],
--  MV 0.25 [Girl,Boy],
--  MV 0.25 [Boy,Girl],
--  MV 0.25 [Boy,Boy]]
```

If the probability distribution uses guard, you can run it using bddist.

```bddist (tossesWithAtLeastOneHead 2)