OCAML延续通过风格
-
28-09-2019 - |
题
我是OCAML的新手,并尝试编写延续传递样式功能,但很困惑我需要在K上传递什么价值
例如,我可以编写一个递归函数,如果列表的所有元素均为否则,则可以返回true。
这样
let rec even list = ....
在CPS上,我知道我需要添加一个参数以通过函数
let rec evenk list k = ....
但是我不知道如何处理这个k,这如何准确起作用
例如,对于这个偶数功能,环境看起来像
val evenk : int list -> (bool -> ’a) -> ’a = <fun>
evenk [4; 2; 12; 5; 6] (fun x -> x) (* output should give false *)
解决方案
延续 k
是从 evenk
并执行“计算的其余部分”,并产生“答案”。答案具有什么类型以及您所说的“计算的其余部分”取决于您使用的CPS 为了. 。 CPS通常不是目的本身,而是考虑到某些目的。例如,在CPS形式中,实现控制操作员或优化尾声非常容易。在不知道您要完成的工作的情况下,很难回答您的问题。
就其价值而言,如果您只是尝试从直接风格转换为延续流程的样式,而您所关心的只是答案的价值,则将身份函数传递到延续是正确的。
下一步是实施 evenk
使用CPS。我将做一个更简单的示例。如果我有直接式功能
let muladd x i n = x + i * n
如果我假设CPS原语 mulk
和 addk
, ,我可以写
let muladdk x i n k =
let k' product = addk x product k in
mulk i n k'
您会发现首先完成了穆斯特摘要,然后它“继续” k'
, ,添加了,最后 continues
和 k
, ,返回呼叫者。关键的想法是在身体内 muladdk
我分配了新的延续 k'
它代表多元ADD函数中的中间点。做你的 evenk
工作您必须至少分配一个这样的延续。
我希望这有帮助。
其他提示
每当我使用CPS时,传递到延续的事情就是您通常会返回呼叫者的东西。在这种简单的情况下,一个不错的“直觉润滑剂”是命名延续“返回”。
let rec even list return =
if List.length list = 0
then return true
else if List.hd list mod 2 = 1
then return false
else even (List.tl list) return;;
let id = fun x -> x;;
示例用法:“甚至[2; 4; 6; 8] id ;;”。
由于您有调用 evenk
正确(具有身份函数 - 有效地将延续风格转换回正常样式),我认为难度在于定义 evenk
.
k
正如诺曼所说,是代表其余计算并产生最终值的延续函数。因此,您需要做的是计算 v
的 even
并将结果传递给 k
, ,返回 k v
而不是只是 v
.
您想将功能的结果作为输入,就好像没有以持续传递方式编写一样。
这是您的功能,它可以测试列表是否只有整数:
(* val even_list : int list -> bool *)
let even_list input = List.for_all (fun x -> x mod 2=0) input
现在让我们继续写 cont
:
(* val evenk : int list -> (bool -> 'a) -> 'a *)
let evenk input cont =
let result = even_list input in
(cont result)
您计算结果您的功能,然后通过 result
继续...