Randomness Setup

Include a StdGen in your model to let you randomize.

Source: LYaH, Input and Output.

Haskell functions are pure, which means the same input must give the same output. A “random number generator” that just puts out different numbers each time you call it is not pure. Instead, in Haskell, the randomization functions output a random value and a new random number generator that will give different results.

Making a StdGen

The best default choice is to use a newStdGen. You could also use mkStdGen if you want to specify the initial “seed” (so the random numbers will all follow the same pattern every time you run the program). Notice the use of let and <- in the examples.

  1. newStdGen: An IO function that uses the system’s random number state to create a random number generator that gives different results every time you run it.

  2. mkStdGen: Provide a seed number, like 109211, and get a random number generator that will produce the same results on every run. Good for debugging.

The code below creates two standard generators. This is just an example. Normally you would only use one.

main = do rng1 <- mkStdGen 109211
          rng2 <- newStdGen
          putStrLn "OK"

Getting Random Numbers

  • In your main method, you can get a random number by calling randomIO. This method avoids using a standard generator, but it only works in main. Note the use of <-.

      main = do
                n <- randomIO :: IO Int
                let m = n `mod` 20  -- 0<=m<20
                print m
    
  • In another function, use random. Make sure you have a type sigature so Haskell knows what to output.

      rand20 :: StdGen -> (Int, StdGen)
      rand20 gen = (n `mod` 20, gen')
         where (n, gen') = random gen
    
      main = do
                g <- newStdGen
                let (n,g2) = rand20 g
                print n
    
  • (randomR) The randomR function gives a random number r in a range low <= r <= high. Notice that both ends of the range are included.

      main = do
                gen <- newStdGen
                let (n, gen') = randomR (1,6) gen :: (Int, StdGen)
                print n
    

Common Problems

  • Copy and pasting examples can mess up indentation. All of the items in a do-block need to line up vertically
  • Variables: regular variables like let x = 5 use a different syntax from “IO variables” like y <- newStdGen.

Notes

  • Avoid getStdGen. Calling getStdGen repeatedly will give the exact same random number generator each time. (It does not “advance the state”.) If you ever have more than one standard generator at a time, this will not be what you want.
Last modified December 14, 2023: Moved location of randomness pages. (603756c)