延续monad和势在必行的monad是否在谈论同样的事情?

时间:2013-12-06 21:59:06

标签: haskell monads

我正在看这篇文章http://lambda-the-ultimate.org/node/2373

他们谈论延续和势在必行的monad。我无法弄清楚两者之间的区别。它们是一样的吗?

2 个答案:

答案 0 :(得分:4)

这篇文章没有讨论命令性的monad - 它谈论的是“强制性思维”,以及命令式语言。 “命令式”一词用于表示一般的编程风格,而不是特定的技术结构。

一般来说,monads以及Haskell中相关的“do-notation”为你提供了一种以命令式方式构建程序的方法,代码表示为一系列动作。

有些monad可能被视为在本质上比其他monad更为必要 - 例如,状态monad明确表达了可以通过每个动作更新的状态的概念,而list monad更多地是关于非确定性的。 / p>

延续monad是一个特定的monad。这是一个非常普遍的,最初也比较难理解。如果我按照“强制性”对monad进行分类,我会把它放在中间位置。

答案 1 :(得分:4)

延续

考虑两个函数的图表,F调用G,传递类型A的值并返回类型B的值:

F       G
|
V
A------>A
        |
        |
        V
B<------B
|

如果你想考虑使用堆栈的实现,那么它是一种堆栈随时间变化的视图。以这种方式看待它对于理解计算时间是很重要的 - 函数F有点“等待”G完成。 (或者你可以看到这是pi演算中的消息交换,显然F被阻止,直到它收到来自G的消息。)

现在,假设,在F得到结果之后,它做了一些更多的计算,返回给调用者等,最终调用者再次调用F,再次,......:

F       G
|
V
A------>A
        |
        |
        V
B<------B
|
...
|
V
A------>A
        |
        |
        V
B<------B
|
...
|
V
A------>A
        |
        |
        V
B<------B
|

坚持下去,但这与在线路上交换F和G相同:

G       F
        |
        V
A<------A
|
...
|
V
B------>B
        |
        |
        V
A<------A
|
...
|
V
B------>B
        |
        |
        V
A<------A
|

如果前面的图表显示F调用G来计算B,那么这最后一个图看起来像G调用F从B计算A.那么,谁在调用谁?

这种二元论被延续的概念所捕捉:函数F可以用两种方式表示;其中一种方式是您想要写它的方式,另一种方式将F表示为F的延续,从G的角度来看F的视图。 F的后一种观点就像从G的返回点写入F,其中B可用。这当然需要以不同的方式重写G,因为它不是“返回”到F,而是必须调用F的延续,期望另一个A,并且“准备好”生成另一个B.此外,这意味着整个程序是也写了,因为现在F而不是“返回”给调用者将不得不调用调用者的继续等等。

到目前为止,我们只看了F一次又一次打电话给G的情况。但是,F只会调用G一次的情况怎么样呢?好吧,从G的观点来看,F的延续将看起来像非终止计算。

为了保持G general,即从其他函数调用G,通常会重写它以接受一个额外的参数,即continuation函数。因此,“F调用G”意味着F通过A并且F连续到G(“H调用G”意味着H通过A并且H连续到G,等等)。这种转变是“继续传递变换”所理解的。

函数调用的基于堆栈的实现中堆栈的返回点是调用者传递给被调用函数的延续 - 因此,continuation传递与基于堆栈的函数调用没有区别,只是使返回点的传递(和“调用”)显式化。

Continuation monad

Continuation monad将计算时间视为效果 - 而不是假设B将立即可用于F,我们可以编写G,以便在B变为可用时调用F的延续。同时,调用F的延续并不假设A将立即可用于G,因此当A变为可用时,将调用G的继续等。

“时间效应”出现在许多其他伪装中 - 在Iteratee,Partiality monad,Codensity monad ......