Haskell monad 和不需要字符串的失败
我有以下 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
它工作得相当好,因为我可以使用自定义类实例化 Error
,并且有一种非常灵活的方法来处理错误。
不过, fail
有点傻,因为它是 String -> 类型。无论是 T 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)
限制。当 monad 堆栈变大时,fail
特别方便,就像当我最终遇到
EitherT BazError (StateT [BazWarning] IO) Foo
Is有办法创建一个与 fail
具有相同行为但限制较少的函数 时类型?或者 fail
是使用深度 haskell 黑魔法实现的吗?
I have the following monad transformer for dealing with errors in 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
It works fairly well, as I can instantiate Error
with a custom class and have a pretty flexible means by which to handle errors.
fail
is a bit silly, though, because it is type String -> EitherT e m
, and the String
restriction can be an annoying way to create errors. I end up with a whole lot of:
instance Error BazError where
strMsg "foo" = FooError -- oh look we have no error context
strMsg "bar" = BarError -- isn't that nice
What I'd like to do is create a new function, like fail
, that is of type a -> e
so that I can remove the (Error e)
restriction. fail
is especially convenient when the monad stack gets large, like when I end up with
EitherT BazError (StateT [BazWarning] IO) Foo
Is there a way to create a function that has the same behavior as fail
with a less restrictive type? Or is fail
implemented using deep haskell dark magic?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,如果 do 块中出现模式匹配失败,则调用
fail
,例如如果您有Just x <- Something
和something
> 的结果是Nothing
。除此之外,fail
是一个普通函数。对于
strMsg "foo" = FooError
等问题,throwError
是否为您的用例提供了更好的界面?Well,
fail
is called if you have a pattern-match failure in a do block, like if you haveJust x <- something
andsomething
's result isNothing
. Apart from that,fail
is an ordinary function.For the problem with
strMsg "foo" = FooError
etc, doesthrowError
offer a nicer interface for your use case?本文可能有用:http: //blog.ezyang.com/2011/08/8-ways-to-report-errors-in-haskell-revisited/
你的 EitherT 已经在标准库中并被调用错误T。请参阅文档: http ://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Error.html#t:ErrorT
fail
现在是一个历史好奇心,并可考虑设计缺陷,以及缺少 Functor a => Monad 是一个约束。在do
表示法中处理失败的模式匹配只是一个有争议的功能。是
fail
最常见的替代品,但还有更多可用的替代品(请参阅文章)。This article may be useful: http://blog.ezyang.com/2011/08/8-ways-to-report-errors-in-haskell-revisited/
Your EitherT is already in the standard library and called
ErrorT
. See the documentation: http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Error.html#t:ErrorTfail
is a historical curiosity now, and may considered a design flaw, along with lack ofFunctor a => Monad a
constraint. It is only a controversial feature to handle failed pattern matches indo
notation.is the most common replacement for
fail
, but more are available (see the article).