
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.
http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Randoms http://learnyouahaskell.com/input-and-output#randomness 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 ghci> n1 493972152 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 ghci> n2 335387100 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. Duncan