Hobby-hacking Eric


simple random numbers in Haskell

Random numbers are the kind of thing I use rarely enough that by the time I want to use them, I have forgotten the relevant details, but frequently enough that I get annoyed whenever it happens.

Hopefully these notes will be useful to somebody in a similar situation.

two things to know

(1) import System.Random

(2) randomIO :: Random a => IO a

The one function you really need to know about is randomIO (The type of this function is Random a => IO a. Don't worry if you do not understand the type; it suffices to know that it involves IO). In this example, we use and generate a random Int:
import System.Random

main =
do r <- randomIO
print (r + 1 :: Int)
-- Note re the ':: Int' above: Haskell can't figure out from
-- the context exactly what type of number you want, so we
-- constrain it to Int
One neat feature is that you can randomly generate anything that implements the Random typeclass. In the example below, we generate a random Bool. Notice how we do not do anything differently, except to treat the result as a bool (i.e. by applying not to it)
import System.Random

main =
do r <- randomIO
print (not r)

A useful exercise, if you know about typeclasses, is to implement Random for one of your own types. The toEnum function may be useful.

more advanced stuff

  1. you can use randomRIO :: Random a => (a,a) -> IO a to generate random numbers constrained within a range
  2. Instead of using the functions randomIO and randomRIO, you can separate obtaining a random number generator, from using the generator. Doing so allows you to minimise your reliance on the IO monad. It also makes your code easier to debug, because you can opt to always pass the same generator to it and make life much more predictable. See the functions random and randomR for details.
  3. a potentially handy trick is to generate an infinite list of random numbers, which you can then pass to a function. See the randoms function for details.

Edit: fixed s/randomR/randomIO/


Anonymous said...

In "two things to know," I think you meant #2 to be randomIO :: Random a => IO a.

kowey said...

Yes! (as opposed to randomR). Thanks!

Nick Knowlson said...

Ha, perfect! This was just the level of detail I needed, thanks :)