Disons que j'ai cette (sans doute induits en erreur) morceau de code autour de la pose:ascenseur soit à ExceptT automatiquement
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
me donne l'erreur suivante:
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
Quelle est la façon la plus standard soulever un Either
dans un ExceptT
? Je pense qu'il doit y avoir un certain chemin depuis Either String
est une instance de MonadError
.
j'ai écrit ma propre fonction de levage:
liftEither :: (Monad m, MonadError a (Either a)) => Either a b -> ExceptT a m b
liftEither = either throwError return
Mais pour moi, cela se sent encore mal puisque je travaille déjà à l'intérieur du transformateur ExceptT
monade.
Qu'est-ce que je fais mal ici? Dois-je structurer mon code différemment?
Qu'en est-il de 'ExceptT. retour'? 'ExceptT = ExceptT (m (Either e a))', donc 'return' vous conduit à' IO (Soit String User) 'et' ExceptT' (comme constructeur/fonction) à 'ExceptT String IO User'. – ibotty