-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StateT's catchError discards changes to state #129
Comments
For reference, I've added a Gist called Monad Transformer Problem. There's a link in the Read Me file to try it in a minimal example program. |
This is a general problem of Monad Transformers (particularly ExceptT/MonadError) not commuting, and the ordering of the layers having important significance. This behavior happens when you layer it with anything that has some sort of output context, like WriterT as well. If you unwrap the types:
You'll see that you either have an error or the Writer context. That means if an error occurs, there's no way to observe any output context for layers above ExceptT/MonadError. |
Thanks for the report. I’m not sure I’d call this a bug; rather, I think it’s a limitation of the transformer approach. I agree with @natefaubion: I see this as one example of a more general issue that the order in which you stack your transformers can affect what’s possible in surprising ways, which is something that would be good to document here. |
lol, I was halfway through writing a response which would have been almost exactly the same as yours |
FWIW, I think that this should be documented in general for the library (transformers don't commute), and particularly with ExceptT/MonadError since it is the one that causes the most trouble. The general guideline is that ExceptT should really always be your outermost layer if you have it... but there are cases where you do really want an error to revert the state (backtracking). |
Also MaybeT. |
StateT's
catchError
doesn't take into account that the state can change in the call to is first parameter:StateT's
functionm
COULD change state and if it does, that state change is lost, i.e. it's neither captured nor is it passed tof
.This is ONLY noticeable when you have a Stack where
StateT
is ABOVEExceptT
otherwiseStateT's
catchError
will NOT be called.After many tests, I've come to the conclusion that this CANNOT be fixed. Here was my initial attempt to fix it:
The problem is that
ExceptT
is BELOWStateT
in the Stack. That means thatm s >>= ...
will Short-circuit, which is NOT the desired behavior here.I cannot see any way to capture the changes made to the state by the first call that won't Short-circuit.
So, the only question that remains is how to communicate this information in the docs. The only place that makes sense in the
StateT
docs.The text was updated successfully, but these errors were encountered: