我是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原语 mulkaddk, ,我可以写

let muladdk x i n k =
  let k' product = addk x product k in
  mulk i n k'

您会发现首先完成了穆斯特摘要,然后它“继续” k', ,添加了,最后 continuesk, ,返回呼叫者。关键的想法是在身体内 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 正如诺曼所说,是代表其余计算并产生最终值的延续函数。因此,您需要做的是计算 veven 并将结果传递给 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继续...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top