# 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.