% Random number generation
The source of this text is a [literate Haskell](http://www.haskell.org/haskellwiki/Literate_programming) file: [random.lhs](random.lhs) that you can download and load into GHC.
We begin by importing the module [`System.Random`](http://hackage.haskell.org/package/random/docs/System-Random.html) for random number generation:
\begin{code}
import System.Random
\end{code}
Random numbers are generated by the function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.haskell}
randomR :: (Int,Int) -> StdGen -> (Int,StdGen)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(Here, the type is specialized for `Int`, but it also works for many other types.)
The first argument is an (inclusive) interval which the result should lie within. The second argument `StdGen` is an abstract value used determine which random number to generate. The result is a random number and a new `StdGen` that can be used to generate new random numbers.
To test `randomR` you first have to create an `StdGen`. Since `StdGen` is an abstract type, it can't be created directly, but only through a helper function, such as:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.haskell}
mkStdGen :: Int -> StdGen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now the user can make up an integer and use that to generate random numbers; e.g:
System.Random> fst (randomR (1,10) (mkStdGen 23456))
8
System.Random> fst (randomR (1,10) (mkStdGen 98765))
1
If you use the same interval and same `StdGen` many times, you will always get the same result:
System.Random> fst (randomR (1,10) (mkStdGen 23456))
8
System.Random> fst (randomR (1,10) (mkStdGen 23456))
8
(After all, `randomR` is a pure function.)
Now one might wonder what's the point of all of this. We're creating a random number from another random number that we had to make up ourselves. But it turns out that it is only for the first use of `randomR` that one has to create an `StdGen`. The result from `randomR` is a pair of a number and a new `StdGen`. By using the new `StdGen` to generate the next random number, it is possible to generate a sequence of independent random numbers.
Here is one way to do that:
\begin{code}
fourRandomNums :: StdGen -> (Int,Int,Int,Int)
fourRandomNums g0 = (a,b,c,d)
where
(a,g1) = randomR (1,10) g0
(b,g2) = randomR (1,10) g1
(c,g3) = randomR (1,10) g2
(d,g4) = randomR (1,10) g3
\end{code}
Note how each `randomR` gets a differet `StdGen`. The above function generates four random numbers from a single `StdGen` (a "seed"):
*Main> fourRandomNums (mkStdGen 234523)
(4,6,10,1)
But as before, we get the same result for the same `StdGen`:
*Main> fourRandomNums (mkStdGen 234523)
(4,6,10,1)
This is all you should need for Lab 2, but not the end of the story. What if you want to create a `StdGen` from a randomly chosen seed? This is a chicken-and-egg problem! Fortunately there is an IO instruction that when executed will fetch a seed from the operating system (which always has a way to generate random values), and use it to create a `StdGen`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.haskell}
newStdGen :: IO StdGen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We can use `newStdGen` as follows (but you need to first understand IO before this will make sense!):
\begin{code}
testFourRandomNums :: IO ()
testFourRandomNums = do
g <- newStdGen
print (fourRandomNums g)
\end{code}
Now we can finally generate independent random numbers without having to worry about seeds:
*Main> testFourRandomNums
(3,2,7,9)
*Main> testFourRandomNums
(7,6,9,9)
*Main> testFourRandomNums
(2,6,9,5)