1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
module Random (
RandomGen(next, split, genRange),
StdGen, mkStdGen,
Random( random, randomR,
randoms, randomRs,
randomIO, randomRIO ),
getStdRandom,
getStdGen, setStdGen, newStdGen
) where
---------------- The RandomGen class ---------------------------
class RandomGen g where
genRange :: g -> (Int, Int)
next :: g -> (Int, g)
split :: g -> (g, g) -- May not exist for all RandomGens
---------------- A standard instance of RandomGen ---------------
data StdGen = ... -- Abstract
instance RandomGen StdGen where ...
-- The show/read instances provide a primitive way to save
-- the state of a random number generator
-- It is expected read (show g) == g
instance Read StdGen where ...
-- read succeeds on *any* string, not only those
-- constructed with show. Hence you can use any
-- string as way to construct a RandomGen.
-- - read guarantees to consume a finite portion of
-- the string
-- - different strings are likely to result in
-- different generators
instance Show StdGen where ...
mkStdGen :: Int -> StdGen
-- Make a StdGen from an Int. Different Ints should result
-- in different generators.
---------------- The Random class ---------------------------
class Random a where
randomR :: RandomGen g => (a, a) -> g -> (a, g)
-- Returns a random value uniformly distributed in [lo,hi]
-- It is unspecified what happens if lo > hi
random :: RandomGen g => g -> (a, g)
-- Return any value of type a.
-- For bounded types, the range is normally the whole type
-- For Fractional types, the range is normally [0..1]
-- For Integer, the range is (arbitrarily) the range of Int
randomRs :: RandomGen g => (a, a) -> g -> [a]
randoms :: RandomGen g => g -> [a]
randomIO :: IO a
randomRIO :: (a,a) -> IO a
-- Default methods
randoms g = x : randoms g'
where
(x,g') = random g
randomRs = ...similar...
randomIO = getStdRandom random
randomRIO range = getStdRandom (randomR range)
instance Random Int where ...
instance Random Integer where ...
instance Random Float where ...
instance Random Double where ...
instance Random Bool where ...
instance Random Char where ...
---------------- The global random 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 non-deterministically; to get
-- deterministic behaviour use setStdGen.
setStdGen :: StdGen -> IO () -- Set the global generator
getStdGen :: IO StdGen -- Get the global generator
getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
-- Use the supplied function to get a value from
-- the current global random generator, g, and update the
-- global generator with the new generator returned
getStdRandom f = do
g <- getStdGen
let (val, g') = f g
setStdGen g'
return val
newStdGen :: IO StdGen
-- Apply split to the current global random generator
-- update it with one of the results and return the other
newStdGen = do
g <- getStdGen
let (s1,s2) = split g
setStdGen s1
return s2
|