假设我有这段(可以说是误导)代码:
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
将 a 提升为的最标准方法是ExceptT
什么?我觉得必须有某种方式,因为Either String
是MonadError
.
我写了自己的提升函数:
liftEither :: (Monad m, MonadError a (Either a)) => Either a b -> ExceptT a m b
liftEither = either throwError return
但对我来说,这仍然感觉不对,因为我已经在
ExceptT
单子变压器内部工作了。
我在这里做错了什么?我应该以不同的方式构建我的代码吗?