Search code examples
haskellmonadsmonad-transformers

Add a monad to the middle of a transformer stack


I'm trying to "semilift" an (ExceptT Error IO Foo) to an (ExceptT Error (StateT Bar IO) Baz).

I've tried lift, fmap lift, and fmap return, and none work; is there a standard idiom here?

> import Control.Monad.Except
> import Control.Monad.State
> data Error
> data Foo
> data Bar
> data Baz
> x = undefined :: ExceptT Error IO Foo
> y = undefined :: (ExceptT Error (StateT Bar IO) Baz) -> a

> f = ??? -- This is what I'm trying to find.

> :t y (f x)
y (f x) :: a

Solution

  • Ignoring the ExceptT newtypes, you have

    IO (Either Error Foo)
    

    And you want

    StateT Bar IO (Either Error Foo)
    

    (I don't see what you want with Baz, so I'm ignoring it.)

    That is just lift. So I believe you should be able to use

    ExceptT . lift . runExceptT
    

    As Alec noted, this can be written using mapExceptT:

    mapExceptT lift