Strictness of modify in Control.Monad.State.Strict

Is there a reason there is no `modify` operation in Control.Monad.State.Strict (and the transformers analogue) which is truly strict in the state? That is, modify' :: Monad m => (a -> a) -> StateM a m () modify' f = get >>= (\x -> put $! f x) While this is admittedly not a difficult piece of code to write, even the suggestion in the documentation that `modify` isn't as strict as one might think would likely save many man-hours of debugging (especially for those who are less familiar with the language, for whom, speaking from experience, strictness issues can pose a major hurdle to adoption) In general it would be nice if the notion of strictness were better addressed in the major libraries' documentation. It's a nuanced issue which is not fully captured by a ".Lazy" or ".Strict" in the module name. Just a thought. Thanks, - Ben

The strictness of Control.Monad.State.Strict has to do with the strictness
of the tuple constructor, not of the state per se. The dichotomy between
Lazy and Strict comes from the competing desires to fake products as
categorical products that don't introduce _|_'s of their own and the lifted
products we have in Haskell which do. The former leads you to the .Lazy
model, the latter leads you to the .Strict model. The former is nicer for
certain lazy knot tying tricks. The latter is easier to reason about when
you start throwing fmap _|_'s around.
However, a Strict State or Writer is not actually strict in the state or
log. This is admittedly a somewhat common misconception.
My concern is that such a combinator would exacerbate this confusion and
that it doesn't generalize. e.g. This trick doesn't generalize to
Strict.Writer, where you can `tell'`, but then you lose than on the next
bind after you lazily smash it into something that is probably just mempty.
I'm not against noting that put/modify is not the thing that we are
'Strict' in more carefully though.
-Edward
On Thu, Sep 27, 2012 at 11:11 PM, Ben Gamari
Is there a reason there is no `modify` operation in Control.Monad.State.Strict (and the transformers analogue) which is truly strict in the state? That is,
modify' :: Monad m => (a -> a) -> StateM a m () modify' f = get >>= (\x -> put $! f x)
While this is admittedly not a difficult piece of code to write, even the suggestion in the documentation that `modify` isn't as strict as one might think would likely save many man-hours of debugging (especially for those who are less familiar with the language, for whom, speaking from experience, strictness issues can pose a major hurdle to adoption)
In general it would be nice if the notion of strictness were better addressed in the major libraries' documentation. It's a nuanced issue which is not fully captured by a ".Lazy" or ".Strict" in the module name.
Just a thought.
Thanks,
- Ben
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Edward Kmett
The strictness of Control.Monad.State.Strict has to do with the strictness of the tuple constructor, not of the state per se. The dichotomy between Lazy and Strict comes from the competing desires to fake products as categorical products that don't introduce _|_'s of their own and the lifted products we have in Haskell which do. The former leads you to the .Lazy model, the latter leads you to the .Strict model. The former is nicer for certain lazy knot tying tricks. The latter is easier to reason about when you start throwing fmap _|_'s around.
However, a Strict State or Writer is not actually strict in the state or log. This is admittedly a somewhat common misconception.
My concern is that such a combinator would exacerbate this confusion and that it doesn't generalize. e.g. This trick doesn't generalize to Strict.Writer, where you can `tell'`, but then you lose than on the next bind after you lazily smash it into something that is probably just mempty.
I understand your concern regarding the inability to generalize to Writer. That being said, does it do any harm to include a truly strict combinator in Strict.State? I for one end up rewriting modify' fairly often (or when I don't, I generally only realize after the first stack overflow). As I mentioned earlier, I think just the presence of "modify'" in the documentation would lead many new Haskellers to catch their mistake before even facing the dreaded "*** Exception: stack overflow". Regardless, it seems there is a general consensus around improving the treatment of laziness in the documentation. Unfortunately, not having mastered this myself, I'm not sure I'd be a terribly good candidate to write this language. Any volunteers? Cheers, - Ben

In general it would be nice if the notion of strictness were better addressed in the major libraries' documentation. It's a nuanced issue which is not fully captured by a ".Lazy" or ".Strict" in the module name.
I agree. I too wasted a significant amount of time hunting down space leaks with were fixed by adding a modify' function. If it had been in the State module along with documentation about the implications, I could have saved time.

I agree. I think part of the issue is that one is in "imperative mindset" when writing this code. For me that seems to make it easier to miss "modify" space leaks in a forM loop, than if I were writing pure code with a fold.
Sent from my cell phone
On Sep 28, 2012, at 3:19 PM, Evan Laforge
In general it would be nice if the notion of strictness were better addressed in the major libraries' documentation. It's a nuanced issue which is not fully captured by a ".Lazy" or ".Strict" in the module name.
I agree. I too wasted a significant amount of time hunting down space leaks with were fixed by adding a modify' function. If it had been in the State module along with documentation about the implications, I could have saved time.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
participants (4)
-
Ben Gamari
-
Edward Kmett
-
Evan Laforge
-
Ryan Newton