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