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.