[Haskell-cafe] help diagnosing space leak with IORef/STRef, just incrementing a million times.

Christopher Done chrisdone at gmail.com
Mon Jan 7 08:14:32 CET 2013

A similar use-case and same solution with IORefs:
http://hpaste.org/diff/80055/80058 Guess which one threw a
stackoverflow and which one ran indefinitely when given a few hundred
million lines of input.

On 7 January 2013 07:35, Albert Y. C. Lai <trebla at vex.net> wrote:
> On 13-01-07 12:12 AM, Thomas Hartman wrote:
>> I have a space leak in a function that increments a number inside
>> IORef or STRef (either lazy or strict).
> IORef and STRef operations do not automatically evaluate contents.
> "writeIORef r (x + 1)" simply stores a pointer to the expression (thunk) "x
> + 1" into the mutable cell. readIORef just reports back a pointer.
> modifyIORef just calls readIORef and writeIORef. No evaluation throughout.
> "modifyIORef incr" where
> incr !x = x + 1
> does not make a difference because it is just "writeIORef r (incr x))",
> i.e., simply stores a pointer to the expression (thunk) "incr x" into the
> mutable cell. The whole process doesn't even care about how many bangs are
> in incr.
> (It is illuminating to consider how "const True (incr x)" does not evaluate
> x. A pointer to True and a pointer to "incr x" are passed to const, then
> const throws away the latter without even looking. See also "const True
> undefined". One day, you will thank "writeIORef r undefined"; I certainly
> did.)
> Same for both Data.STRef.Strict and Data.STRef.Lazy. They do not mean what
> you think. Here is what they mean:
> Data.STRef.Strict means what Control.Monad.ST.Strict means
> Data.STRef.Lazy means what Control.Monad.ST.Lazy means
> Control.Monad.ST.Strict means that the following hangs:
> x = head (runST list) where
>   list :: ST s [Bool]
>   list = do {xs <- list; return (True : xs)}
> Control.Monad.ST.Lazy means that the above terminates and gives the answer
> True.
> (Up to this point, same story for Control.Monad.State.Strict and
> Control.Monad.State.Lazy.)
> I still have not understood Control.Monad.ST.Lazy enough to articulate its
> full semantics, but I have some more examples to show what it does:
> http://hpaste.org/63925
> By understanding what "Lazy" in Control.Monad.ST.Lazy means, you also see
> what "Strict" does *not* mean.
> In IO or Control.Monad.ST.Strict, use
>   let y = x+1 in y `seq` write[IO/ST]Ref r y
> to expedite the evaluation of x+1. Using the same idea, you may write your
> own modify[IO/ST]RefNOW to evaluate while updating.
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list