如何将shift / reset转换为delimcc?

时间:2013-01-21 01:14:41

标签: functional-programming ocaml continuations delimited-continuations

我正在研究Oleg和Asai划定的“傻瓜”续篇(http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf)但本文使用的是shift /重置形式主义,而不是奥列格的delimcc中提供的提示。所以我有几个问题:

首先,什么是提示?为什么在shift和其他函数中传递?知道什么是subcont也不错,但我愿意跳过这个,因为我只是想通过论文。此外,shiftshift0之间的区别是什么?它们与论文中的shift如何对应。

此外,delimcc中的reset是什么?我的直觉告诉我,new_promptpush_prompt某种程度上与reset相对应。但我在这里也需要澄清一些。

编辑:我能够从论文中翻译一个简单的例子,我的直觉证明是正确的。但是我想要对这些差异进行真正的解释,为什么delimcc就是这样的。这是两个版本,如果有人感兴趣

纸张:

reset (fun () -> 3 + shift (fun _ -> 5 * 2) - 1)

Delimcc:

let _ = let open Delimcc in
  let np = new_prompt () in
  push_prompt np (fun () -> 3 + (shift np (fun _ -> 5 * 2)) - 1)

1 个答案:

答案 0 :(得分:10)

我建议您阅读this paper的开头,这是Oleg的delimcc演示文稿的期刊版本。这样可以让您对delimcc有一个合理的理解,让您将文章的移位/重置示例移植到delimcc的多提示设置。

您可能感兴趣的两个引号。第一个是我上面提到的期刊版本:

  

已经熟悉分界控件的读者可能将delimcc视为普通的概括   移位/重置以控制任意多种“风味”的分隔符。函数new_prompt创建一个新的唯一控件分隔符或提示符   味道。表达式push_prompt p (fun () -> e),概括   reset e,将控制分隔符p放在堆栈上,然后评估e;   take_subcont p f删除堆栈的前缀到最近的堆栈   标有给定p的框架。堆栈的移除部分,与   终止分隔符p被截断,被打包为一个延续对象   抽象类型子包并传递给take_subcont的参数f。函数push_subcont可能会将已删除的堆栈帧放回堆栈中   在不同的上下文中,从而恢复捕获的分隔延续。

第二个来自GNU Guile's documentation

  

还在吗?因此,当实现像call-with-prompt这样的分隔控制运算符时,需要做出两个决策。首先,处理程序是在提示符之内还是之外运行?让处理程序在提示符下运行允许处理程序内的中止返回到相同的提示处理程序,这通常很有用。但是它会阻止来自处理程序的尾调用,所以它不那么通用。

     

同样,调用捕获的延续会恢复提示吗?我们再次对方便与正确的尾调用进行权衡。

     

这些决定在Felleisen F 运算符中捕获。如果continuation和处理程序都没有隐式添加提示,则运算符称为 -F - 。 Guile的call-with-promptabort-to-prompt就是这种情况。

     

如果continuation和handler都隐式添加提示,则运算符为 + F + shiftreset就是这样的运营商。

总结:你是正确的,调用new_prompt来获取提示,然后push_prompt安装它是获取reset的方法。实际上,您只需要调用new_prompt一次,并且可以始终推送到同一个全局提示符,并获得通常的shift / reset行为(声明不同的提示只会为您提供更多信息)自由)。

最后,shift可以使用delimcc的原语进行定义,这就是在库中完成的操作。 shift调用take_subcont,立即重新安装(相同)提示,并向用户提供将重启中止计算的函数。 shift0执行相同的操作,但不会重新安装提示。在delimcc代码中:

let shift p f = take_subcont p (fun sk () ->
  push_prompt p (fun () -> (f (fun c -> 
    push_delim_subcont sk (fun () -> c)))))

let shift0 p f = take_subcont p (fun sk () ->
  f (fun c -> push_delim_subcont sk (fun () -> c)))