zig*_*tar 7 continuations scala
有一些关于Scala延续的问题(这里和这里).但答案只是试图解释它.所以在这个问题中,我要求正确定义什么(Scala的)分隔的延续.我不需要一个例子(虽然它可能会有所帮助)并要求一个简单易懂的形式化,如果它有帮助,甚至可能忽略输入.
形式化应该涵盖语法(不是语法意义上的,而是相似的f is a function and c is a foo
)和语义(计算的结果是什么).
延续插件中实现的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\nreset { 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里面的程序变成你可以访问的函数(这个过程称为具体化)。在上述情况下,功能是:
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\nshift[A, B, C](fun: ((A) => B) => C): A \n
Run Code Online (Sandbox Code Playgroud)\n\n延续将是 (A => B) 函数,无论谁在其中编写代码,都可以shift
决定用它做什么(或不做什么)。只要将其退回,您就会真正感受到它的作用。其结果reset
就是具体化计算本身:
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 注释类型的
不纯的计算被转换为Shift[A, B, C]
对象(现在ControlContext[A, B, C]
在标准库中称为)。这些Shift
对象正在扩展延续单子。它们的正式实现见 EPFL论文第 4 页第 3.1 节。该map
方法将纯计算与Shift
对象结合起来。该flatMap
方法将不纯计算与Shift
对象结合起来。
延续插件按照 EPLF论文第 3.4 节中给出的概要执行代码转换。基本上,shift
都变成了Shift
物体。之后发生的纯表达式与map组合,不纯表达式与flatMap组合(更多规则参见图4)。最后,一旦所有内容都转换为封闭的重置,如果所有内容都进行类型检查,则所有映射和平面映射之后最终 Shift 对象的类型应该是Shift[A, A, C]
。该reset
函数具体化了所包含的Shift
,并以恒等函数作为参数来调用该函数。
总之,我认为 EPLF 论文确实包含了对所发生情况的正式描述(第 3.1 和 3.4 节以及图 4)。我提到的教程有精心挑选的示例,这些示例给定界延续带来了很好的感觉。
\n