Diciamo che ho questo (forse indurre in errore) pezzo di codice, che in giro:ascensore O per Exceptt automaticamente
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
mi dà il seguente errore:
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
Qual è il modo più standard sollevando un Either
in un ExceptT
? Ritengo che ci sia un modo in cui Either String
è un'istanza di MonadError
.
ho scritto la mia propria funzione di sollevamento:
liftEither :: (Monad m, MonadError a (Either a)) => Either a b -> ExceptT a m b
liftEither = either throwError return
Ma per me questo si sente ancora sbagliata dato che sto già lavorando all'interno del trasformatore Monade ExceptT
.
Cosa sto facendo di sbagliato qui? Dovrei strutturare il mio codice in modo diverso?
E a proposito di "Eccetto". return'? 'ExceptT = ExceptT (m (Either e a))', quindi 'return' ti porta a' IO (Either String User) 'e' ExceptT' (come costruttore/funzione) a 'ExceptT String IO User'. – ibotty