Safe Haskell | Trustworthy |
---|

# Random number generators

The class `RandomGen`

provides a common interface to random number
generators.

The `next`

operation returns an `Int`

that is uniformly distributed
in the range returned by `genRange`

(including both end points),
and a new generator.

The `split`

operation allows one to obtain two distinct random number
generators. This is very useful in functional programs (for example, when
passing a random number generator down to recursive calls), but very
little work has been done on statistically robust implementations of
`split`

([Random, Random]
are the only examples we know of).

genRange :: g -> (Int, Int)Source

The `genRange`

operation yields the range of values returned by
the generator.

It is required that:

The second condition ensures that `genRange`

cannot examine its
argument, and hence the value it returns can be determined only by the
instance of `RandomGen`

. That in turn allows an implementation to make
a single call to `genRange`

to establish a generator's range, without
being concerned that the generator returned by (say) `next`

might have
a different range to the generator passed to `next`

.

The default definition spans the full range of `Int`

.

## Standard random number generators

The `StdGen`

instance of `RandomGen`

has a `genRange`

of at least 30 bits.

The result of repeatedly using `next`

should be at least as statistically
robust as the *Minimal Standard Random Number Generator* described by
[Random, Random].
Until more is known about implementations of `split`

, all we require is
that `split`

deliver generators that are (a) not identical and
(b) independently robust in the sense just given.

The `Show`

and `Read`

instances of `StdGen`

provide a primitive way to save the
state of a random number generator.
It is required that

.
`read`

(`show`

g) == g

In addition, `reads`

may be used to map an arbitrary string (not necessarily one
produced by `show`

) onto a value of type `StdGen`

. In general, the `Read`

instance of `StdGen`

has the following properties:

- It guarantees to succeed on any string.
- It guarantees to consume only a finite portion of the string.
- Different argument strings are likely to result in different results.

## The global random number generator

There is a single, implicit, global random number generator of type
`StdGen`

, held in some global variable maintained by the `IO`

monad. It is
initialised automatically in some system-dependent fashion, for example, by
using the time of day, or Linux's kernel random number generator. To get
deterministic behaviour, use `setStdGen`

.

getStdRandom :: (StdGen -> (a, StdGen)) -> IO aSource

Uses the supplied function to get a value from the current global
random generator, and updates the global generator with the new generator
returned by the function. For example, `rollDice`

gets a random integer
between 1 and 6:

rollDice :: IO Int rollDice = getStdRandom (randomR (1,6))

Applies `split`

to the current global random generator,
updates it with one of the results, and returns the other.

# Random values of various types

With a source of random number supply in hand, the `Random`

class allows the
programmer to extract random values of a variety of types.

randomR :: RandomGen g => (a, a) -> g -> (a, g)Source

Takes a range *(lo,hi)* and a random number generator
*g*, and returns a random value uniformly distributed in the closed
interval *[lo,hi]*, together with a new generator. It is unspecified
what happens if *lo>hi*. For continuous types there is no requirement
that the values *lo* and *hi* are ever produced, but they may be,
depending on the implementation and the interval.

random :: RandomGen g => g -> (a, g)Source

The same as `randomR`

, but using a default range determined by the type:

randomRs :: RandomGen g => (a, a) -> g -> [a]Source

Plural variant of `randomR`

, producing an infinite list of
random values instead of returning a new generator.

randoms :: RandomGen g => g -> [a]Source

Plural variant of `random`

, producing an infinite list of
random values instead of returning a new generator.

# References

- FW Burton and RL Page,
*Distributed random number generation*, Journal of Functional Programming, 2(2):203-212, April 1992. - SK Park, and KW Miller, /Random number generators - good ones are hard to find/, Comm ACM 31(10), Oct 1988, pp1192-1201.
- DG Carta, /Two fast implementations of the minimal standard random number generator/, Comm ACM, 33(1), Jan 1990, pp87-88.
- P Hellekalek,
*Don\'t trust parallel Monte Carlo*, Department of Mathematics, University of Salzburg, http://random.mat.sbg.ac.at/~peter/pads98.ps, 1998. - Pierre L'Ecuyer, /Efficient and portable combined random number generators/, Comm ACM, 31(6), Jun 1988, pp742-749.

The Web site http://random.mat.sbg.ac.at/ is a great source of information.