You cannot exchange an arbitrary pair of monads . But you can exchange these two separate monads. The easiest way to understand is whether you extend the newtype in the definitions of these monad transformers.
Considering
newtype StateT sma = StateT { runStateT :: s -> m (s, a) }
and
newtype ExceptT ema = ExceptT { runExceptT :: m (Either ea) }
the newtype extension in your first type expression gives us an 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 ea)
Note that Either e (s, a) may or may not contain s , while (s, Either ea) always. Now you can go from the last to the first, just traverse with a tuple inside the function, but to switch to another path some domain-specific arguments are required: if the calculation causes an error, then we must discard the state without changes until the error catches. (Is it right to do this? I find this rather controversial.)
stateTEitherToExceptTState :: (s -> Either e (s, a)) -> (s -> (s, Either ea)) stateTEitherToExceptTState fs = case fs of Left e -> (s, Left e) Right sa -> fmap Right sa
source share