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.