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 <tre...@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@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe