当前位置:  开发笔记 > 编程语言 > 正文

提升自动提取到ExceptT

如何解决《提升自动提取到ExceptT》经验,为你挑选了1个好方法。

假设我有这个(可以说是误导的)代码片段:

import System.Environment (getArgs)
import Control.Monad.Except

parseArgs :: ExceptT String IO User
parseArgs =
  do
    args <- lift getArgs
    case safeHead args of
      Just admin -> parseUser admin
      Nothing    -> throwError "No admin specified"

parseUser :: String -> Either String User
-- implementation elided

safeHead :: [a] -> Maybe a
-- implementation elided

main =
  do
    r <- runExceptT parseArgs
    case r of
      Left  err -> putStrLn $ "ERROR: " ++ err
      Right res -> print res

ghc 给我以下错误:

Couldn't match expected type ‘ExceptT String IO User’
            with actual type ‘Either String User’
In the expression: parseUser admin
In a case alternative: Just admin -> parseUser admin

什么是提升的最标准的方式EitherExceptT?我觉得必须有一些方法,因为Either String是一个实例MonadError.

我写了自己的提升功能:

liftEither :: (Monad m, MonadError a (Either a)) => Either a b -> ExceptT a m b
liftEither = either throwError return

但对我来说,这仍然是错误的,因为我已经在ExceptTmonad变换器内部工作了 .

我在这做错了什么?我应该以不同方式构建代码吗?



1> Cactus..:

你可以将parseUser类型概括为

parseUser :: (MonadError String m) => String -> m User 

然后它可以在at m ~ Either String和at m ~ ExceptT String m'(如果只是Monad m')工作,无需任何手动提升.

做到这一点的方法是基本取代RightreturnLeftthrowErrorparseUser的定义.


请注意,该限制`MonadError字符串M` GHC需要`FlexibleContexts`扩展(见http://stackoverflow.com/a/22795830/905686).
推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有