Functional programming 如何将换档/复位转换为手动模式?

Functional programming 如何将换档/复位转换为手动模式?,functional-programming,ocaml,continuations,delimited-continuations,Functional Programming,Ocaml,Continuations,Delimited Continuations,我在研究Oleg和Asai的《傻瓜》论文中的定界连续体(http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf),但本文使用移位/重置形式,而不是Oleg的Delimc中可用的提示内容。所以我有几个问题: 首先,什么是提示?为什么在shift和其他函数中传递?。知道什么是分包也不错,但我愿意跳过,因为我只想看完这篇论文。另外,shift和shift0之间的区别是什么,以及它们如何与本文中的shift相对应 另外,MCC中的reset是

我在研究Oleg和Asai的《傻瓜》论文中的定界连续体(http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf),但本文使用移位/重置形式,而不是Oleg的Delimc中可用的提示内容。所以我有几个问题:

首先,什么是提示?为什么在
shift
和其他函数中传递?。知道什么是分包也不错,但我愿意跳过,因为我只想看完这篇论文。另外,
shift
shift0
之间的区别是什么,以及它们如何与本文中的
shift
相对应

另外,MCC中的
reset
是什么?我的直觉告诉我,
new\u prompt
push\u prompt
以某种方式对应于
reset
。但我也需要一些澄清

编辑:我能从论文中翻译出一个简单的例子,我的直觉证明是正确的。然而,我想要一个真正的解释的差异,为什么他们是这样的。这里有两个版本,以防有人感兴趣

论文:

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)

我建议您阅读的开头,这是Oleg的
delimcc
演示文稿的期刊版本。这将使您对
delimcc
有一个合理的了解,从而将文章的移位/重置示例移植到
delimcc
的多提示设置中

你可能会感兴趣的两句话。第一个是我上面提到的期刊版本:

熟悉分隔控件的读者可能会将delimcc视为普通控件的泛化 shift/reset可控制任意多个“风格”的分隔符。函数
new\u prompt
创建一个新的、唯一的 风味表达式
push\u prompt p(fun()->e)
,泛化 将控制定界符
p
放在堆栈上,然后计算
e
take_subc p f
删除堆栈的前缀,直到最近的堆栈 用给定的
p
标记的框架。堆栈的已移除部分,带有 终止分隔符
p
cut-off被打包为 抽象类型subc并传递给
take_subc
的参数
f
。函数
push_subc
可能会将移除的堆栈帧放回堆栈上 在不同的上下文中,从而恢复捕获的带分隔符的继续

第二个是来自

还在这儿吗?因此,当一个人实现一个分隔的控制操作符,比如带有提示符的
调用时,他需要做出两个决定。首先,处理程序是在提示符内运行还是在提示符外运行?让处理程序在提示符内运行,允许处理程序内的中止返回到同一个提示符处理程序,这通常很有用。但是,它会阻止来自处理程序的尾部调用,因此不太通用

类似地,调用捕获的延续是否会恢复提示?再一次,我们要权衡方便与适当的尾部调用

这些决策在Felleisen F操作符中捕获。如果continuations和处理程序都未隐式添加提示,则该运算符称为–F–。Guile的
调用带有提示符
中止以提示符
就是这种情况

如果continuation和handler都隐式添加提示,则运算符为+F+
shift
reset
就是这样的操作员

总而言之:调用
new\u prompt
获取提示,然后
push\u prompt
安装它是获取
reset
的方法,这是对的。事实上,您只需要调用一次
new\u提示符
,就可以一直推到同一个全局提示符,并获得通常的
shift
/
reset
行为(声明不同的提示符只会给您更多的自由)

最后,
shift
可以用
delimcc
的原语定义,这就是在库中所做的
shift
调用
take_subc
,立即重新安装(相同)提示符,并向用户提供一个函数,该函数将重新启动中止的计算
shift0
执行相同的操作,只是没有重新安装提示符。在
mcc
代码中:

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)))

狗屎/重置?我不熟悉这个概念。SO上没有[oleg]标记吗?看起来好像
shift
操作符正在实现用于部分求值的语法糖。也就是说,
shift
有一个参数,但它是隐式的,它的插入由它旁边的主体中的下划线表示。如果有人正在为移位/重置概念而挣扎,那么这个额外的糖可能会增加一层难度。显式提示推送只是因为它纯粹是一个库,并且宿主语言缺少宏。对于某些元编程,可能会有
reset NAME(…..shift NAME(…)
生成较低级别的代码,其中NAME动态绑定到显式分配的提示符,然后按下提示符。我计划将delimcc实现概念移植到Lisp方言中,当然我不会让编码器经历两步提示分配过程,因为我有
defmacro