使用递归在lambda演算中创建有序对的列表

时间:2018-04-28 03:35:53

标签: recursion lambda lambda-calculus calculus

我的输入是两个列表:l = [x1,x2,x3,...,xn]和k = [y1,y2,y3,...,yn]

我想要一个y = [(x1,y1),(x2,y2),(x3,y3)...(xn,yn)]输出。

如何将递归应用于我的代码?我可以用第一个项目来做          f = \l k. (cons (pair (head l) (head k)) empty)但我不明白如何使用递归来创建其他项目。

功能" head"返回列表的第一项和函数" tail"返回没有第一项的列表。

1 个答案:

答案 0 :(得分:0)

自然地,这完全取决于您如何在Lambda演算中实现元组,列表等。但是,假设使用标准功能性cons列表,并且两个列表的长度相同,并且您已经定义了以下助手,其中一些您已经引用:

cons    -- construct a list from a node and another list
empty   -- the empty list
head    -- retrieve the first node value of a list
tail    -- retrieve all but the first node of a list
pair    -- pair values into a tuple
isEmpty -- return `true` if a list is `empty`, `false` otherwise
true    -- return the first argument
false   -- return the second argument

然后我们可以递归压缩列表,如下所示:

ZIP = λlk. isEmpty l -- "if the list is empty…"
           empty     -- "return an empty result. Else…"
           (cons     -- "return a new list, containing…"
               (pair (head l) (head k))  -- "the zipped heads, and…"
               (ZIP  (tail l) (tail k))) -- "everything else zipped."

当然,问题在于原始的lambda演算没有具有递归。您不能在其自己的定义中引用函数名称。答案是使用fixed-point combinator, e.g. the famous Y combinator

ZIP = Y (λzlk. isEmpty l empty (cons (pair (head l) (head k)) (z (tail l) (tail k)))

Y的定义是:

Y = λf.(λx.f(x x))(λx.f(x x))

弄清该的工作原理是令人印象深刻的一点,虽然这个问题的范围不大,但是使用却很简单。通常,如果您具有所需的(但在原始LC中是非法的)递归定义,如下所示:

R = λ ??? . ??? R ???

您可以改为将其写为完全合法,非递归的定义:

R = Y (λr ??? . ??? r ???)

换句话说,在函数中添加一个新参数,该参数代表作为递归函数,并使用Y为您连接所有内容。 Y可以从零开始发明递归是非同寻常的,也是它如此著名的原因。