
Dear Ryan, Thanks a lot for your support and for pointing out a problem with my approach to forcing the state. I was aware of this issue but I didn't know there was a standard solution. It is indeed very natural to let each type specify how to evaluate itself. I will try this technique on the nearest occasion. Incidentally, the link to Control.Parallel.Strategies from the latest GHC User Guide is broken... --Alexei Ryan Ingram wrote:
On Sat, Jan 9, 2010 at 2:23 AM, Alexei Kitaev
wrote: Reading the discussion related to your blog, I realized that strict State is different in that it does not actually force the state. But forcing can be achieved by wrapping all actions with the following function:
sState :: (s -> (a,s)) -> State s a sState f = State $ \s -> case f s of (a,s') -> s' `seq` (a,s')
I hope that somebody will answer my other questions about the operational semantics and optimizations.
Hi Alexei, you have a ton of great points but I wanted to discuss an issue with this one.
It's unusual that this is what you want either; since it only reduces the state to WHNF. For example, if your state is a string, this only evaluates enough to know whether or not the string is empty at each step, and you can still get into trouble with code like this:
put ("xxx" ++ some_bad_computation)
which leave bottoms inside of your state which won't show up until later.
Several attempts to solve this problem exist, but the most commonly used one is the "rnf" strategy from Control.Parallel.Strategies, which uses a typeclass to allow each type to specify how to evaluate itself completely.
-- ryan