5

我认为我缺少对 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,我认为我不应该为自己定义。

在不改变类型的情况下,最直接的制作gatewayinner合作方式是什么?

4

1 回答 1

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"

MonadErrorErrorT和都有实例Either,因此您可以inner同时使用。

于 2012-04-04T18:10:58.463 回答