c++ - Maybe 和 Either 单子(monad)、短路和性能

标签 c++ performance haskell functional-programming monads

Functional Programming in C++ ,第 214 页,引用 expected<T,E> monad 与 Haskell 的 Either 相同, 阅读

[...] as soon as any of the functions you're binding to returns an error, the execution will stop and return that error to the caller.

然后,在下面的标题中,它显示

If you call mbind [equivalent to Haskell's >>=] on an expected that contains an error,, mbind won't even invoke the transformation function; it will just forward that error to the result.

这似乎是在“调整”之前写的内容。 (我很确定 LYAHRWH 在某处强调没有短路;如果你记得在哪里,请提醒我。)

事实上,我对 Haskell 的理解是,在单子(monad)绑定(bind)链中,所有绑定(bind)都是真实发生的;然后他们如何处理作为第二个参数传递给他们的函数,取决于特定的 monad。

Maybe的情况下和 Either ,当绑定(bind)传递给 Nothing 时或 Left x参数,则忽略第二个参数。

不过,在这两种特定情况下,我想知道这样做是否会降低性能

justPlus1 = Just . (+1)
turnToNothing = const Nothing
Just 3 >>= turnToNothing >>= justPlus1
                         >>= justPlus1
                         >>= justPlus1
                         >>= justPlus1
                         >>= justPlus1

因为在这些情况下,链不能真正做除它所做的之外的任何事情

Nothing >>= _ = Nothing
Left l >>= _ = Left l

最佳答案

考虑以下表达式:

result :: Maybe Int
result = x >>= f >>= g >>= h

当然,在该表达式中,x::Maybe a 用于某些 a,以及每个 fgh 是函数,h 返回 Maybe Int 但管道的中间类型可以是任何包装在 也许。也许 f::String -> Maybe Stringg::String -> Maybe Charh::Char -> Maybe Int

让我们也明确关联性:

result :: Maybe Int
result = ((x >>= f) >>= g) >>= h

要对表达式求值,每个绑定(bind) (>>=) 实际上都必须被调用,但函数fg,或h。最终,对 h 的绑定(bind)需要检查其左侧参数,以确定它是 Nothing 还是 Just something;为了确定我们需要调用对 g 的绑定(bind),并决定我们需要调用对 f 的绑定(bind),这必须至少查看 x。但是,一旦这些绑定(bind)中的任何一个产生了 Nothing,我们只需为在每一步检查 Nothing 付费(非常便宜),而不是为调用(可能昂贵的)下游函数付费。

假设 x = Nothing。然后 f 的绑定(bind)会检查它,看到 Nothing,并且根本不会调用 f。但是我们仍然需要绑定(bind)它的结果,以便知道它是否为 Nothing。这一直沿着链向下,直到我们最终得到 result = Nothing,调用了 >>= 三次但没有函数 fg,或h

EitherLeft 值的行为相似,而其他 monad 可能有不同的行为。列表可以调用每个函数一次、多次或不调用;元组 monad 只调用每个函数一次,没有短路或其他多重性特征。

关于c++ - Maybe 和 Either 单子(monad)、短路和性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63943706/

相关文章:

c++ - STL 容器性能概述

haskell - hsc2hs 和 c2hs 之间的区别?

haskell - 如何在 Haskell 中向新类型添加相等比较 (==)

c++ - 如何使用带有 `--gcov-tool` 标志的 lcov?

C++ ofstream浮点编码

c++ - C++ 编译器是否针对不同平台(Linux、Windows 等)多次编写?

c++ - 在二维数组 C++ 中读取图像并保存

C++ 线程安全和时间效率 : why does thread with mutex check sometimes works faster than without it?

python-3.x - 矢量化自定义 RGB -> 灰度转换

haskell - 如何避免 zipWith self 引用中的无限循环?