我正在尝试构建一个函数,该函数接受给定数量的参数并始终返回相同的值。
这是家庭作业的一部分。提供了一个提示:
“k-way T”是一个带有k个参数并且总是返回T的函数。“0-way T”只是T.
其中k作为Church Numeral提供,T是lambda表达式True(\ x。\ y.x)。
完整的任务是提供一个计算k-way OR函数的lambda表达式。在'boolean'参数之前提供'boolean'参数的数量。例如:
((OR 3) F T F)
但是现在我正在尝试创建带有k个参数并且总是返回T.k作为第一个参数提供。
((TRUE 2) T F) == T
所以基本上我不想创建一个函数,每个教会数字'迭代'都有一个参数。
但不知怎的,我完全陷入困境。
我可以只用一个教堂数字吗?或者我需要递归(Y-Combinator)?
一般来说:是否有支持lambda表达式创建的好工具(例如可视化)。
我对lambda演算的力量感到非常惊讶,我真的很想学习它。但我不知道怎么......
提前致谢
我将展示如何实现TRUE
函数。由于k
不是固定的,你需要一个定点组合器(Y
会这样做,但它不是唯一的定点组合器)。首先,关于我在下面使用的符号的几个词:iszero
(取教会数字,检查它是否为教会零并返回教会布尔值),T
(教会编码的真实布尔值),pred
(前身教会数字的功能)和Y
(定点组合器)。
let TRUE = Y (λr. λn. (iszero n) T (λx. (r (pred n))))
请注意,let
不是lambda演算语法的一部分,它是引入名称的metasyntax(对我们而言)。
这样做如下:Y
将r
参数转换为“self” - 当函数调用r
时它会调用自身。为了说明这一点,我将把上面的内容重写为递归形式(警告:它仅用于说明目的,lambda演算不允许这样做;因为所有函数都是匿名的,你不能用他们的名字来调用它们 - 有对此没有办法):
let TRUE = λn. (iszero n) T (λx. (TRUE (pred n)))
我已经脱掉了λr.
部分并用r
取代了TRUE
(再次,请不要在你的作业中这样做,它不是有效的lambda演算)。
这个定义更容易理解:如果TRUE
被调用像这样TRUE 0
它只返回T
,否则它返回一个参数的函数,它包含(n - 1)个参数的函数,基本上代表n个参数的函数。
至于你关于工具的问题:一种方法是使用Scheme / Racket - 这将有助于检查你的“lambda演算代码”运行应该如何。例如,以下是Racket中TRUE
的实现:
(define (Y f)
((lambda (x) (x x))
(lambda (x) (lambda (a) ((f (x x)) a)))))
(define TRUE
(Y (lambda (r)
(lambda (n)
(if (zero? n)
#t
(lambda (x) (r (sub1 n))))))))
;; tests
> (TRUE 0)
#t
> ((TRUE 1) #f)
#t
> (((TRUE 2) #f) #f)
#t
> ((((((TRUE 5) #f) #f) #f) #f) #f)
#t
我应该补充一点,我在这里使用了内置的布尔值,整数,if-expression,sub1
,zero?
而不是Church编码的。否则会使这个例子更大(或不完整)。
我现在也在做那个确切的功课,我只是想告诉你和未来的任何读者,绝对不需要定点组合器。
要从Pk:=(k-way T, k-way OR)
对到Pk+1:=(k+1-way T, k+1-way OR
对,你只需应用函数lambda Pk. (lambda a b c. c a b) (lambda arg. Pk (lambda x y. x)) (lambda arg. Pk arg)
。
简而言之,这个函数解构你的对并构造一对新的,再吃一个参数。新的k+1-way OR
只是来自k-way OR
in的Pk
案例,如果论证是F
,则论证是k-way T
或T
。
现在你需要做的唯一一件事就是将它应用于起始对P0:=(lambda a b c. c a b) (lambda x y. x) (lambda x y. y)
,你可以使用教会数字n来做。最后你只需要取这对的第二部分,你应该留下一个n-way OR
。