Generate multiple random numbers in haskell

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.