Edward Kmett ekmett at gmail.com
Mon Jul 26 09:12:56 EDT 2010

```On Sun, Jul 25, 2010 at 11:39 AM, michael rice <nowgate at yahoo.com> wrote:

> Hi All,
>
>
>                            Exercises
>
>    1. Implement a function rollNDiceIO :: Int -> IO [Int] that,
>       given an integer, returns a list with that number of pseudo-
>       random integers between 1 and 6.
>
>
> After a lot of learning what not to do, this is the best I could come up
> with.
>
> rollNDiceIO :: Int -> IO [Int]
> rollNDiceIO n = mapM (\x -> randomRIO(1,6)) (replicate n 1)
>
> I know, ugly, but at least I got it to work. What's a better way to
> generate this list?
>
>
An even better method lets the list be generated lazily.

import Data.Functor ((<\$>))
import Random

rollDice :: IO [Int]
rollDice =  randomRs (1,6) <\$> newStdGen

rollNDice :: Int -> IO [Int]
rollNDice n = take n <\$> rollDice

This is important because randomRIO has to peek at an MVar to determine the
current value of the random number seed _for each die rolled_, but using
randomRs on a fresh StdGen only has does so once.

Moreover, it gives you the more general 'rollDice' funtion, which can give
you an infinite list of random dice rolls. Trying to implement that function
using the approach you used will lead to a computation that won't terminate.

-Edward Kmett
-------------- next part --------------
An HTML attachment was scrubbed...