我的输入是两个列表: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"返回没有第一项的列表。
答案 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
可以从零开始发明递归是非同寻常的,也是它如此著名的原因。