更新

几年后再回顾,发现当时编写的内容大量是错的,因此重写。

起因

学习 CPS 实现过程中对单子的思考。

说明

ConT 主要的优点在于可以传递计算结果,和 monad 下用 lambda 传递不同,这个传递是可以显示中断的。因为单子约束的是 Monad (Cont r)~,~a 每次计算输入的值,也就是上一次计算的结果值,对最后一层则就是输出的结果,而中间传递的是最后做为输出时计算的最后一步。

以 Monad Maybe 为对比,后续计算的 lambda 是当前 bind 的分支,由当前 bind 处理完(前一次计算)输入后调用。实际逻辑与过程式相似,很直观。

Cont 是通过 lambda 包装来实现的。不同于 Monad 的逻辑,它是将当前操作包进一个新 lambda 里,由新的调用者来接收这一参数。对于后续计算 lambda 的编写来说,与 monad 是一样,都是接受一个参数。但因为其包装方式的不同,可以对每次重新包装时的 lambda 做修改。~callCC~ 就是在这样的前题下,通过重新包装的 lambda,来忽略传入的值,仅返回指定的值,就可以绕过后续所有的计算。

其实 Monad (Cont r) 与正常的 monad 是一样的,关键在于 callCC 的重新包装与 lambda 配合产生了提前结束的效果。与 ReaderaskStateset 等是同样的手法。

参考 wiki已经做到比较好的说明。这里只是扩展一下自己的理解。