
Hi Udo, On Aug 24, 2006, at 7:22 AM, Udo Stenzel wrote:
Hi Gregory,
Gregory Wright wrote:
step :: Tag s -> ST s (Maybe Integer) step t = do c <- readSTRef (count t) s <- readSTRef (state t) writeSTRef (count t) (c - 1) writeSTRef (state t) (nextState s) if (c <= 0) then return Nothing else return (Just c)
just looking at the program, this seems to be the problem: writeSTRef does not force the evaluation of the stored value. So after repeated calculation, you end up storing not the current counter and state, but something like (nextState (...(nextState (nextState initState))...)). The counter is evaluated for the conditional at the end, so it doesn't exhibit this problem. Your computation runs to its end, then that deeply nested expression is evaluated and exhausts the control stack. Try this instead:
writeSTRef (state t) $! nextState s
If TagState is a more complicated data type, you may also need strict fields in there.
[This comes up so often, shouldn't there be an FAQ about it somewhere? It could even offer a guideline along the lines of "Whenever you repeatedly update some value, chances are that you want to force strict evaluation."]
I agree this should be a FAQ. Perhaps I should write it up for the performance section of the wiki? Looking back I see my mental error was that I thought I was doing what you and everyone else correctly suggested: writeSTRef (state t) $! nextState s but what I actually typed was writeSTRef (state t) (nextState $! s) which of course doesn't help. Another telling example of the fact that coffee is not an entirely adequate substitute for sleep. Best, Greg
Udo. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe