Scala延续的正式定义

zig*_*tar 7 continuations scala

有一些关于Scala延续的问题(这里这里).但答案只是试图解释它.所以在这个问题中,我要求正确定义什么(Scala的)分隔的延续.我不需要一个例子(虽然它可能会有所帮助)并要求一个简单易懂的形式化,如果它有帮助,甚至可能忽略输入.

形式化应该涵盖语法(不是语法意义上的,而是相似的f is a function and c is a foo)和语义(计算的结果是什么).

huy*_*hjl 4

延续插件中实现的Scala分隔延续是对Danvy 和 Filinski引入的移位重置控制运算符的改编。请参阅他们的《抽象控制表示控制:1990 年和 1992 年对 CPS 转换的研究》论文在类型化语言的背景下,EPFL 团队的工作扩展了Asai的工作。请参阅此处2007 年论文

\n\n

这应该是很形式主义吧!我浏览了这些,不幸的是它们需要流利的 lambda 演算符号。

\n\n

另一方面,我发现了以下使用 Shift 和 Reset 进行编程的 教程,当我开始将示例转换为 Scala 以及当我到达“2.6 如何提取分隔延续” 部分时,感觉我确实在理解上有了突破

\n\n

运算reset符界定程序的一部分。shift用于存在值(可能包括单位)的位置。你可以把它想象成一个洞。我们用 \xe2\x97\x89 来表示它。

\n\n

那么让我们看看下面的表达式:

\n\n
reset { 3 + \xe2\x97\x89 - 1 }                  // (1)\nreset {                              // (2)\n  val s = if (\xe2\x97\x89) "hello" else "hi"\n  s + " world"\n}\nreset {                              // (3)\n  val s = "x" + (\xe2\x97\x89: Int).toString\n  s.length\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

所做shift的就是将reset里面的程序变成你可以访问的函数(这个过程称为具体化)。在上述情况下,功能是:

\n\n
val f1 = (i: Int) => 3 + i - 1       // (1)\nval f2 = (b: Boolean) => {\n   val s = if (b) "hello" else "hi"  // (2)\n   s + " world"\n}\nval f3 = (i: Int) => {               // (3)\n   val s = "x" + i.toString\n   s.length\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

该函数称为延续,并作为参数提供给它自己的参数。移位签名是:

\n\n
shift[A, B, C](fun: ((A) => B) => C): A \n
Run Code Online (Sandbox Code Playgroud)\n\n

延续将是 (A => B) 函数,无论谁在其中编写代码,都可以shift决定用它做什么(或不做什么)。只要将其退回,您就会真正感受到它的作用。其结果reset就是具体化计算本身:

\n\n
val f1 = reset { 3 + shift{ (k:Int=>Int) => k } - 1 }\nval f2 = reset { \n           val s =\n             if (shift{(k:Boolean=>String) => k}) "hello"\n             else "hi"\n           s + " world"\n         }\nval f3 = reset {\n           val s = "x" + (shift{ (k:Int=>Int) => k}).toString\n           s.length\n         }\n
Run Code Online (Sandbox Code Playgroud)\n\n

我认为具体化方面确实是理解 Scala 分隔延续的一个重要方面。

\n\n

从类型角度来看,如果函数k具有类型 (A=>B),则shift具有类型A@cpsParam[B,C]。类型C完全取决于您选择在shift. cpsParam返回用或注释的类型的表达式在 EPFL 论文中cps被限定为不纯的。这与纯粹的这与没有 cps 注释类型的

\n\n

不纯的计算被转换为Shift[A, B, C]对象(现在ControlContext[A, B, C]在标准库中称为)。这些Shift对象正在扩展延续单子。它们的正式实现见 EPFL论文第 4 页第 3.1 节。该map方法将纯计算与Shift对象结合起来。该flatMap方法将不纯计算与Shift对象结合起来。

\n\n

延续插件按照 EPLF论文第 3.4 节中给出的概要执行代码转换。基本上,shift都变成了Shift物体。之后发生的纯表达式与map组合,不纯表达式与flatMap组合(更多规则参见图4)。最后,一旦所有内容都转换为封闭的重置,如果所有内容都进行类型检查,则所有映射和平面映射之后最终 Shift 对象的类型应该是Shift[A, A, C]。该reset函数具体化了所包含的Shift,并以恒等函数作为参数来调用该函数。

\n\n

总之,我认为 EPLF 论文确实包含了对所发生情况的正式描述(第 3.1 和 3.4 节以及图 4)。我提到的教程有精心挑选的示例,这些示例给定界延续带来了很好的感觉。

\n