How to convert StateT g (Either E) T
to ExceptT E (StateT g Identity) T
?
Probably, some mix of traverse
and hoist
could be useful here.
You can't exchange an arbitrary pair of monads. But you can exchange these two particular monads. It's easiest to understand if you expand the newtype
s in the definitions of those monad transformers.
Given
newtype StateT s m a = StateT { runStateT :: s -> m (s, a) }
and
newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) }
expanding the newtype
s in your first type expression gives us the isomorphism
StateT s (Either e) a <-> s -> Either e (s, a)
whereas for the second we get
ExceptT e (StateT s Identity) a <-> s -> (s, Either e a)
Note that Either e (s, a)
may or may not contain an s
, whereas (s, Either e a)
always does. Now, one can go from the latter to the former just by traverse
ing the tuple inside the function, but going the other way requires some domain-specific reasoning: if the computation throws an error then we should plumb the state through unchanged to the catcher of the error. (Is this the right thing to do? I find it rather debatable.)
stateTEitherToExceptTState :: (s -> Either e (s, a)) -> (s -> (s, Either e a))
stateTEitherToExceptTState f s =
case f s of
Left e -> (s, Left e)
Right sa -> fmap Right sa
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With