1) System.Random.randoms
Simplest way to generate an infinite list of random numbers.
import System.Random as R
main = do
gen <- R.getStdGen
print $ take 10 $ R.randoms gen
Internally, randoms
construct an infinite list:
randoms g = (\(x,g') -> x : randoms g') (random g)
2) State monad
The previous method is simple, but doesn't return a generator, so effectively, the generated numbers are the only one available. To get some random variable and a new generator, the state monad can be used.
import Control.Monad.State
genRng :: RandomGen g => State g Int
genRng = do
gen <- get
let (val, gen') = R.random gen
put gen'
return val
main = do
gen <- R.getStdGen
-- get 10 random numbers and the final generator
let (vals, finalGen) = runState (replicateM 10 genRng) gen
print vals
This approach also lends itself to more complex operation, for example, returning a tuple:
genRngTuple = do
gen <- get
let (val1, gen') = R.random gen
let (val2, gen'') = R.random gen'
put gen''
return (val1, val2)
3) Simplifing with state
The genRng
function is a bit verbose and can be simplified with state
import Control.Monad.State
genRng' :: RandomGen g => State g Int
genRng' = state R.Random
main = do
gen <- R.getStdGen
print $ evalState (replicateM 10 genRng') gen
This approach is much nicer when returning tuple for example:
genRngTuple' = do
a <- state R.random
b <- state R.random
return (a, b)
This way, no need to do any bookkeeping with the internal state.