[Haskell-cafe] better way to do this?
duncan.coutts at googlemail.com
Sun Oct 4 09:20:53 EDT 2009
On Sun, 2009-10-04 at 05:11 -0700, Michael Mossey wrote:
> Duncan Coutts wrote:
> > Others have already answered but I'd like to suggest that you avoid
> > using IO here. There's no need for this to be impure.
> Can you point me to a tutorial that covers the basics of randomness in
> Hasell? I find it very confusing.
The main thing to realise is that random number generators are pure and
predictable. Given the state of a random number generator, if you ask
for a random number, it always gives the same answer. It has to, because
it is pure.
Let's make one, and seed it with the starting state 12345
ghci> :module System.Random
ghci> let g0 = mkStdGen 12345
Now we can ask for the next random number in the sequence:
ghci> let (n1, g1) = next g0
Now of course if we asked for the random number from g0 again then we
must get the same result. But notice that when we use 'next' it also
gives us back g1 which is the next state of the random number generator.
ghci> let (n2, g2) = next g1
So this is the basic way that random number generators work in a pure
language. The generator has to be passed around the pure function, for
example from one recursion to the next.
So you end up with pure functions like:
shuffle :: RandomGen g => g -> [x] -> [x]
Another approach is to hide the 'g' inside a monad. That's what
MonadRandom is all about. eg:
shuffle :: [x] -> Rand [x]
The tutorials above explain about the other random functions, for
getting values of different types (not just Int) and restricted ranges
of number etc.
Of course at some point you want to seed the random number generator
with some initial genuinely random value (not like the 12345 we used
above). That is the only place in your random-handling code that needs
to do IO. All the rest of it can be pure.
More information about the Haskell-Cafe