我有以下用于处理 Haskell 错误的 monad 转换器。
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
它工作得很好,因为我可以实例化
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
我想做的是创建一个新函数,比如
fail
,即类型 a -> e
这样我就可以删除 (Error e)
限制。 fail
当 monad 堆栈变大时特别方便,比如当我结束时EitherT BazError (StateT [BazWarning] IO) Foo
有没有办法创建一个与
fail
具有相同行为的函数?限制较少的类型?或者是 fail
使用 deep haskell 黑魔法实现?
最佳答案
那么,fail
如果您在 do 块中遇到模式匹配失败,则会调用它,就像您有 Just x <- something
一样和 something
的结果是 Nothing
.除此之外,fail
是一个普通的函数。
对于 strMsg "foo" = FooError
的问题等等,是否throwError
为您的用例提供更好的界面?
关于Haskell monads 和不需要字符串的失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8602117/