Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Random variable library in Haskell, with Functor, Applicative and Monad instances.
Haskell
branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
Control/Monad
.gitignore
LICENSE
README.md
Setup.hs
rand-vars.cabal

README.md

Haskell - rand-vars

This library provides the Rand applicative monad. This monad represent computations that can return values at random. The distribution of values can be specified using provided functions.

A monad transformer, RandT, is also available.

The class RandPicker allows to pick an element at random out of Rand. Instances for Rand, RandT and IO are provided.

Creation of random variables

rand

rand returns a random element, following distribution of underlying Random (from System.Random) instance.

decision :: Rand Bool
decision = rand

inRange

inRange returns an element at random from the specified range. The distribution follows the one of the underlying Random instance.

die :: Rand Int
die = inRange (1, 6)

oneOf

oneOf models a random variable that returns one with equal probabilities of the elements of the list.

color :: Rand String
color = oneOf ["red", "green", "blue"]

If the list contains n elements, constructing the random variable takes O(n) time. Picking an element out of the random variable is constant time.

fromFreqs

fromFreqs allows to specify the frequency of each element. Note that the frequencies don't have to add up to 1. Negative frequencies are considered null.

biaisedDie :: Rand Int
biaisedDie = fromFreqs [1 `withFreq` 1.2, 
                        2 `withFreq` 1.1, 
                        3 `withFreq` 1, 
                        4 `withFreq` 1, 
                        5 `withFreq` 0.9, 
                        6 `withFreq` 0.8]

If the list contains n elements, constructing the random variable takes O(n) time. Picking an element out of the random variable takes O(log(n)) time.

If the sum of frequencies is 0, the behavior is unspecified.

Note that withFreq is simply an alias for (,), the pair constructor.

Picking value from random variables.

Any monad that has an instance of RandPicker can pick an element at random out of a random variable. To do so, simple use the pick function.

pick :: RandPicker m => Rand a -> m a

IO, Rand and RandT, are instances of RandPicker.

MonadRand

For convenience, MonadRand can be used to express the contraint that the RandPicker must also be a Monad.

Meaning that, instead of:

foo :: (RandPicker m, Monad m) => ...

One can write:

foo :: (MonadRand m) => ...

Code example

The following is a more complete example on the Casino theme!

import Control.Monad.Random
import Control.Applicative
import Control.Monad

data Slot = Lemon | Cherry | Strawberry | Orange | Bar | Seven deriving (Enum, Show)

data Combination = Combination Slot Slot Slot deriving Show

fairSlot = oneOf [Lemon .. Seven]

fairCombination = Combination <$> fairSlot <*> fairSlot <*> fairSlot

biasedSlot = fromFreqs [Lemon `withFreq` 1, 
                        Cherry `withFreq` 1, 
                        Strawberry `withFreq` 1.2, 
                        Orange `withFreq` 1.1,
                        Bar `withFreq` 0.9,
                        Seven `withFreq` 0.8]

biasedCombination = Combination <$> biasedSlot <*> biasedSlot <*> biasedSlot


aTripToAMachine = do
         combination <- fromFreqs [fairCombination `withFreq` 10, 
                                   biasedCombination `withFreq` 5]
         rounds      <- inRange (5, 50)
         replicateM rounds combination

aTripToTheCasino = do
         trips <- fmap (*3) $ inRange (1, 10)
         fmap concat $ replicateM trips aTripToAMachine

main = pick aTripToTheCasino >>= print
Something went wrong with that request. Please try again.