私がこの(間違いなく誤解を招く)コードの一部を置いているとしましょう:
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
モナド変換子の内部で作業しているので、これはまだ間違っていると感じています。
ここで何が間違っていますか?コードを別の方法で構成する必要がありますか?