如何编写 Monad 将计算链接在一起

发布于 2025-01-11 02:03:01 字数 516 浏览 0 评论 0原文

我正在编写我的第一个 monad 实例,所以如果我遗漏了一些明显的东西,请原谅。

我想做这样的事情:

readStuffFromDatabase >>= function1 >>= ... >>= functionN >>= writeStuffToDatabase

function1 ... functionN 是业务逻辑。任何业务逻辑都可以返回 DoNothing,这显然会阻止任何进一步的计算。

以下是我的问题:

  1. 我是否以正确的方式思考这个问题?这种方法能否带来惯用的代码、良好的性能等,还是已经注定了?

  2. 我应该如何定义一个类型来将任意数量的计算链接在一起?对我来说模糊的是所有 monad 实例都已经这样做了,而我需要的只是一个普通的 monad 实例吗? (比如也许?)或者我需要更复杂的东西吗?

I am writing my first monad instance so please forgive if I'm missing something obvious.

I want to do something like this:

readStuffFromDatabase >>= function1 >>= ... >>= functionN >>= writeStuffToDatabase

function1 ... functionN are business logic. Any business logic can return DoNothing which should obviously prevent any further computation.

Here are my questions:

  1. Am I thinking about the problem in the right way? Can this approach lead to idiomatic code, good performance, etc. or is it already doomed?

  2. How should I define a type intended to chain arbitrary amounts of computation together? What's fuzzy to me is do all monad instances already do that and all I need is a vanilla monad instance? (Like Maybe?) Or do I need something more sophisticated?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(1

远昼 2025-01-18 02:03:01

简短版本:Monad 几乎肯定会把你逼到墙角。您需要 Applicative 相反,或者最多是一个选择性的应用程序。

假设您选择一个 monad,将其命名为 M,并执行一些类似 numEmployees :: M Int 之类的操作。现在我写道:

do
    n <- numEmployees
    if n > 10
        then computeTaxes
        else dollars 1000 <$ DoNothing

要执行此操作,您需要在知道n之前决定是否采用else分支。不可能。

此处妨碍您的 monad 的基本特征是,后续操作可以在决定要做什么之前检查早期操作返回的值。应用函子不支持这一点,因此更适合您希望进行的静态分析。

Short version: Monad is almost certainly going to paint you into a corner. You need Applicative instead, or at most, a selective applicative.

Suppose you go for a monad, name it M, and have some action like numEmployees :: M Int or something. Now I write:

do
    n <- numEmployees
    if n > 10
        then computeTaxes
        else dollars 1000 <$ DoNothing

To execute this action, you need to decide whether the else branch gets taken before knowing n. Not possible.

The fundamental feature of monads that's in your way here is that later actions can inspect the values returned by earlier actions before deciding what to do. Applicative functors do not support that, and so are more amenable to the kind of static analysis you're hoping to do.

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