Given a mtl
monad stack, e.g. ExceptT String (WriterT String (State s a))
, how can I evaluate the inner state monad without needing to unwrap the outer monads?
have :: ExceptT String (WriterT String (State s)) a
f :: State s a -> a
want :: ExceptT String (WriterT String Identity) a
I can do this by calling runExceptT
followed by runWriterT
and repacking the results afterward but it seems like the wrong way to accomplish this.
As far as I tried, something like fmap
or similar won't work because the monad transformer stack is treated as an entire monad on it's own. What I need is a functionality to "split" the monad transformer stack like this:
split :: (MonadTrans s, Monad t) => (s t) a -> s (t a)
Either I haven't found this function or the solution works entirely differently.
The approach that seems simplest in this particular case is to use the MFunctor
instances of the ExceptT e
and WriterT w
transformers:
import Control.Monad.Morph
floop :: Monad m
=> s
-> ExceptT e (WriterT w (StateT s m)) a
-> ExceptT e (WriterT w m) a
floop s = hoist (hoist $ flip evalStateT s)
Since State s = StateT s Identity
, the slight generalization above is immediate.