Random number in Haskell [duplicate]

This is a common barrier for new Haskell programmers. You want to escape IO, and it takes a while to figure out the best way to do so. The Learn You A Haskell tutorial has a good explanation of one way to generate random numbers using the state monad, but it still has to be seeded using getStdGen or newStdGen, which are in IO.

For simple cases you can just do something like

myPureFunction :: Float -> Float
myPureFunction x = 2 * x

main :: IO ()
main = do
    -- num :: Float
    num <- randomIO :: IO Float
    -- This "extracts" the float from IO Float and binds it to the name num
    print $ myPureFunction num

So you see, you can get your random number in main, then pass that value to a pure function that does the processing.

You may be asking yourself why there’s all this work to generate random numbers in Haskell. There are numerous good reasons, most of which have to do with the type system. Since generating random numbers requires modifying the state of the StdGen in the operating system, it has to live inside IO, otherwise you could have a pure function that gives you different results each time.

Imagine this contrived scenario:

myConstant :: Int
myConstant = unsafePerformIO randomIO

blowUpTheWorld :: IO ()
blowUpTheWorld = error "Firing all the nukes"

main :: IO ()
main = do
    if even myConstant
        then print "myConstant is even"
        else blowUpTheWorld

If you ran this a few times, chances are that you would end up “firing all the nukes”. Obviously, this is bad. myConstant should be, well, constant, but each time you run the program you’d get a different value. Haskell wants to guarantee that a pure function will always return the same value given the same inputs.

It may be annoying right now, but it’s a powerful tool in the functional programmer’s kit.

Leave a Comment