我想我对monad变形金刚有一些基本的了解,因为我发现自己编写了这段代码:
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"
虽然这有效,但我认为这可以更优雅地完成。特别是,我正在寻找liftError
的替代品,我认为我不应该为自己定义。
让gateway
和inner
一起工作而不改变其类型的最简单方法是什么?
答案 0 :(得分:6)
如果您只是稍微更改一下类型,则根本不需要进行任何提升。
{-# 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
包含ErrorT
和Either
的实例,因此您可以将inner
用作两者。