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
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
genRng function is a bit verbose and can be simplified with
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.
Here are three ways to generate multiple random values. These method works for any kind of stateful computation. The monad approach gives more control, allowing any function like
s -> (a, s) to be embedded inside, abstracting away any work to thread the state across calls.
The State monad can also be generalized using monad transformer. Some good read about the transformer approach: