Haskell monad 和不需要字符串的失败

发布于 2024-12-22 14:17:52 字数 1078 浏览 3 评论 0原文

我有以下 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

够运 2024-12-29 14:17:52

好吧,如果 do 块中出现模式匹配失败,则调用 fail ,例如如果您有 Just x <- Somethingsomething > 的结果是Nothing。除此之外,fail 是一个普通函数。

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

Well, fail is called if you have a pattern-match failure in a do block, like if you have Just x <- something and something's result is Nothing. Apart from that, fail is an ordinary function.

For the problem with strMsg "foo" = FooError etc, does throwError offer a nicer interface for your use case?

怪我太投入 2024-12-29 14:17:52

本文可能有用: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 表示法中处理失败的模式匹配只是一个有争议的功能。

throwError :: MonadError e m => e -> m a

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:ErrorT

fail is a historical curiosity now, and may considered a design flaw, along with lack of Functor a => Monad a constraint. It is only a controversial feature to handle failed pattern matches in do notation.

throwError :: MonadError e m => e -> m a

is the most common replacement for fail, but more are available (see the article).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文