modifyIORef lazy? (was Re: BLACKHOLE in heap profile)
Tom Pledger
Tom.Pledger@peace.com
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.
Yes.
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 ($!).