尾部递归与延续

时间:2016-11-10 23:07:17

标签: recursion tail-recursion ml

如何将以下ML代码转换为尾递归函数?我已经盯着它,并试图弄清楚几个小时,我无法看到如何。

datatype Tree = NULL | NODE of Tree*Tree | VAL of int;
fun dup(NULL) = NULL
 | dup(VAL(y)) = NODE(VAL(y),VAL(y))
 | dup(NODE(y1,y2)) = NODE(dup(y1), dup(y2));

1 个答案:

答案 0 :(得分:2)

转换为延续传递样式在这里(相对)直截了当 - 递归是一个棘手的案例。

重写右侧有时可以更容易地看到模式。

| dup (NODE (y1, y2)) = let val left = dup y1
                            val right = dup y2
                        in
                            NODE (left, right)

我们需要同时抓住leftright并将它们组合起来 CPS的不同之处在于我们传递一个接收这些值而不是直接接收它们的函数,然后我们让给我们的延续处理结果。

命名延续“return”,它可能如下所示:

fun dup_cont NULL return = return NULL (* Trivial *)
    (* duplicate the value and return it *)
  | dup_cont (VAL y) return = return (NODE (VAL y, VAL y))
    (* recurse, grab the result.
       recurse again, grab result.
       combine the two results and return *)
  | dup_cont (NODE (y1, y2)) return = 
        dup_cont y1 (fn left => dup_cont y2 (fn right => return (NODE (left, right))))