haskell - 自动将 Either 提升到 exceptT

标签 haskell monads monad-transformers either lifting

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

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
Either 最标准的吊装方式是什么?进入 ExceptT ?
我觉得从Either String 开始一定有什么办法是 MonadError 的一个实例.

我写了自己的提升函数:
liftEither :: (Monad m, MonadError a (Either a)) => Either a b -> ExceptT a m b
liftEither = either throwError return

但对我来说,这仍然感觉不对,因为我已经在里面工作了ExceptT单子(monad)变压器。

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

最佳答案

你可以概括parseUser的类型为

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

然后它可以在 m ~ Either String 上工作在 m ~ ExceptT String m' (如果只有 Monad m' )无需任何手动提升。

这样做的方法是基本替换RightreturnLeftthrowErrorparseUser的定义。

关于haskell - 自动将 Either 提升到 exceptT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34588488/

相关文章:

haskell - 自动重新计算结果

haskell - 尝试实现 (>>=) 函数以创建自定义 monad 转换器时键入错误

Haskell:在 FreeMonad 解释器中使用 MonadState 进行内存

haskell - 变量的Lambda演算变化及应用问题

haskell - 从边列表构建图

haskell - 自由单子(monad)和自由操作

scala - 为什么我们需要 Scala 中的 Monad Transformers?

database - 处理变压器堆栈中的数据库访问

haskell - monad 变压器和多个 monad 的堆叠

haskell - 防止 Yampa/Animas 中 SF 相互依赖的无限循环