Haskell monads和一个不需要字符串的失败

So8*_*res 5 monads haskell monad-transformers

我有以下monad转换器来处理Haskell中的错误.

instance (Monad m, Error e) => Monad (EitherT e m) where
    return = EitherT . return . return
    m >>= k  = EitherT $ do
            a <- runEitherT m
            case a of
                Left  l -> return (Left l)
                Right r -> runEitherT (k r)
    fail = EitherT . return . Left . strMsg
Run Code Online (Sandbox Code Playgroud)

它运行得相当好,因为我可以Error使用自定义类进行实例化,并且具有非常灵活的方法来处理错误.

fail但是,有点傻,因为它是类型String -> EitherT e m,String限制可能是一种令人讨厌的创建错误的方法.我最终得到了很多:

instance Error BazError where
    strMsg "foo" = FooError -- oh look we have no error context
    strMsg "bar" = BarError -- isn't that nice
Run Code Online (Sandbox Code Playgroud)

我想要做的是创建一个新的函数,比如fail类型,a -> e以便我可以删除(Error e)限制.fail当monad堆栈变大时,特别方便,就像我最终一样

EitherT BazError (StateT [BazWarning] IO) Foo
Run Code Online (Sandbox Code Playgroud)

有没有办法创建一个fail与限制较少的类型具有相同行为的函数?或者fail使用深度haskell黑魔法实现?

Dan*_*her 7

好吧,fail如果你在一个do块中有一个模式匹配失败,就会被调用,就好像你有Just x <- somethingsomething结果一样Nothing.除此之外,fail是一个普通的功能.

对于strMsg "foo" = FooError等问题,是否throwError为您的用例提供了更好的界面?