StateT + IO behavior

Tomasz Zielonka tomasz.zielonka at
Sat Apr 16 04:14:33 EDT 2005

On Fri, Apr 15, 2005 at 08:17:13PM -0700, Isaac Jones wrote:
> Can anyone help me explain this behavior?

I'm not sure this will be a satisfactory explanation, but if you look at
StateT's implementation it is quite obvious that is must work this way:

    newtype StateT s m a = StateT {runStateT :: (s -> m (a, s))}

for m = IO and s = Int this is

    StateT {runStateT :: (Int -> IO (a, Int))}

The new state is returned as part of IO action result. If there is an
exception, you don't get the new state.

> Is this because it's not really "safe" to embed the IO monad in a
> StateT monad?

I guess it depends on what you mean by "safe". In some situations this
might be the expected behaviour.

> The strange thing I see is that the errorHandler function is the only
> one whose modifications to the state persist.
If this is a problem, maybe try catching the exception deeper, for
>   (s, n) <- runStateT (stateFun 1 >> catchError stateErr errorHandler >> stateFun 10)
>                        0

Best regards

More information about the Libraries mailing list