randomIO causing stack overflow ?

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Mon Mar 2 17:02:58 EST 2009

On Sun, 2009-03-01 at 00:34 +0100, timtoorop at quicknet.nl wrote:
> Hi,
> I was just messing with randomIO for no particular reason, and it suddenly caused a stack overflow which would only go away after restarting ghci.
> Here's what I see in ghci 6.8.2
> http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=1642
> mmorrow posted the same using ghci 6.10.1
> which gave the same stack overflow
> Anyone got any idea what causes this funny behavior?

class Random a where

  ... snip ...

  randomIO :: IO a
  randomIO = getStdRandom random

getStdRandom :: (StdGen -> (a,StdGen)) -> IO a
getStdRandom f = atomicModifyIORef theStdGen (swap . f)
  where swap (v,g) = (g,v)

So what happens when we do
_ <- randomIO
_ <- randomIO
_ <- randomIO

is that we're calling getStdRandom random many times and not inspecting
the random numbers generated. That means the IORef containing the global
rnd state (theStdGen) is now an unevaluated thunk that looks rather

snd . random . snd . random . snd . random $ mkStdRNG 0 

Now, if instead of doing it 3 times like above, you do it 100,000 times
then you get a very big thunk indeed. Evaluating this thunk overflows
the stack. Calling randomIO again and evaluating the result does not
help. The internal IORef still contains the stack-overflowing thunk.

Once in this situation we're stuffed. We've thrown away all the values
that we could force that would let us evaluate the thunk when it was
still small enough to do so.

This problem could probably be fixed by adjusting the definition of
getStdRandom like:

getStdRandom :: (StdGen -> (a,StdGen)) -> IO a
getStdRandom f = atomicModifyIORef theStdGen $! (swap . f)
  where swap (v,g) = g `seq` (g,v)

Though even that may not do it. The StdGen data and stdNext functions
may not be strict enough.

data StdGen = StdGen Int32 Int32

It's not strict in the Int32 fields. I doubt that it needs to be so


More information about the Libraries mailing list