Inserting ErrorT at the base of transformer stack

Viewed 226

What is the best way to run a code with type t (ErrorT String IO) a from within a t IO a monad? Consider the code below:

module Sample where

import System.IO
import Control.Monad.Reader
import Control.Monad.Error

type Env = String

inner :: ReaderT Env (ErrorT String IO) ()
inner = do
    s <- ask
    fail s

outer :: ReaderT Env IO ()
outer = do
    env <- ask
    res <- lift $ runErrorT $ runReaderT inner env
    case res of
        Left err -> liftIO $ hPutStrLn stderr err
        Right _ -> return ()
    outer

This works, but I've been looking for a more graceful way of inserting ErrorT at the base of my stack. Especially that I'm using several different monad transformer stacks in my project and writing the above for each of them is quite tedious.

I was looking for something like:

outer :: ReaderT Env IO ()
outer = do
    res <- (hoist runErrorT) inner
    ...

But I cannot use hoist due to type mismatch.


Edit:

I use StateT in some of my stacks and that's the reason for trying to put ErrorT at the base and not on the top.

The outer is supposed to be an infinite loop.

2 Answers
Related