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

How To Write a Monad to Chain Computations Together

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

我想做这样的事情:

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

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

这是我的问题:

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

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

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

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

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

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

单子的基本特征是,后面的动作可以在决定做什么之前检查前面的动作返回的值。 Applicative functor 不支持它,因此更适合您希望进行的那种静态分析。