I think I'm missing some basic understanding of monad transformers, because I found myself writing this code:
import Control.Monad.Identity
import Control.Monad.Error
liftError :: Either String Int -> ErrorT String Identity Int
liftError x = do case x of
Right val -> return val
Left err -> throwError err
gateway :: Bool -> ErrorT String Identity Int
gateway = liftError . inner
inner :: Bool -> Either String Int
inner True = return 5
inner False = throwError "test"
While this works, I think that this could be done more elegantly. In particular, I'm looking for a replacement of liftError, which I think I shouldn't have to define for myself.
What would be the most straightforward way to make gateway and inner work together without changing their type?
If you just change the types a little, you don't have to do any lifting at all.
{-# LANGUAGE FlexibleContexts #-}
gateway :: Bool -> ErrorT String Identity Int
gateway = inner
inner :: MonadError String m => Bool -> m Int
inner True = return 5
inner False = throwError "test"
MonadError has instances for both ErrorT and Either, so this way you can use inner as both.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With