Copyright | (c) The University of Glasgow 2001 |
---|---|

License | BSD-style (see the file LICENSE in the 'random' repository) |

Maintainer | libraries@haskell.org |

Stability | stable |

Portability | portable |

Safe Haskell | Trustworthy |

Language | Haskell98 |

This library deals with the common task of pseudo-random number generation. The library makes it possible to generate repeatable results, by starting with a specified initial random number generator, or to get different results on each run by using the system-initialised generator or by supplying a seed from some other source.

The library is split into two layers:

- A core
*random number generator*provides a supply of bits. The class`RandomGen`

provides a common interface to such generators. The library provides one instance of`RandomGen`

, the abstract data type`StdGen`

. Programmers may, of course, supply their own instances of`RandomGen`

. - The class
`Random`

provides a way to extract values of a particular type from a random number generator. For example, the`Float`

instance of`Random`

allows one to generate random values of type`Float`

.

This implementation uses the Portable Combined Generator of L'Ecuyer [System.Random] for 32-bit computers, transliterated by Lennart Augustsson. It has a period of roughly 2.30584e18.

# Random number generators

class RandomGen g where Source

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.

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`

.

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`

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

## 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
[System.Random, System.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 a Source

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.

randomRIO :: (a, a) -> IO a Source

A variant of `randomR`

that uses the global random number generator
(see System.Random).

A variant of `random`

that uses the global random number generator
(see System.Random).

# 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.