modifyIORef lazy? (was Re: BLACKHOLE in heap profile)

Tom Pledger
Sat, 19 Apr 2003 12:29:13 +1200

Hal Daume III writes:
 | but when i replace:
 |   modifyIORef r <E>
 | with
 |   v <- readIORef r
 |   writeIORef r $! <E>
 | I no longer run into this heap problem and the program runs much
 | more quickly.


When (f $! x) is evaluated, first x is forced to Weak Head Normal
Form, and then (f x) is evaluated.

In this case, (writeIORef r $! <E>) is evaluated early, thanks to the
strict sequencing of actions in the IO monad, so <E> is evaluated
early too.

You should get the same result with

    modifyIORef r $! <E>

 | even if I use (modifyIORef f (\x -> id $! <E> x)), which I thought
 | would fix it, there is still a heap problem.

That's different, because the application of ($!) does not get caught
up in the sequencing of actions.  In answer to the subject line,
modifyIORef updates a reference strictly, but the thing the reference
refers to may be a suspended computation.

In this case, after the modifyIORef the reference points to a
suspension of

    (\x -> id $! <E> x) the_thing_previously_pointed_to

and the evaluation hasn't yet reached the ($!).