我正在尝试构建一个接受给定数量的参数并始终返回相同值的函数。
这是家庭作业的一部分。提供了一个提示:
“k-way T”是一个接受 k 个参数并始终返回 T 的函数。“0-way T”就是 T。
其中 k 作为 Church Numeral 提供,T 是 True (\x.\yx) 的 lambda 表达式。
完整的任务是提供一个计算 k 路 OR 函数的 lambda 表达式。其中“布尔”参数的数量在“布尔”参数之前提供。例如:
((OR 3) F T F)
Run Code Online (Sandbox Code Playgroud)
但现在我正在尝试创建一个接受k 个参数并始终返回T 的程序。k作为第一个参数提供。
((TRUE 2) T F) == T
Run Code Online (Sandbox Code Playgroud)
所以基本上我不想创建一个函数,为每个教会数字“迭代”多一个参数。
但不知怎的,我完全陷入困境。
我可以只使用教堂数字来做到这一点吗?或者我需要递归(Y-Combinator)吗?
一般来说:是否有任何好的工具(例如可视化工具)支持创建 lambda 表达式。
我真的对 lambda 演算的力量感到惊讶,我真的很想学习它。但我不知道如何...
提前致谢
我将展示如何实现该TRUE函数。\n由于k不固定,因此您需要一个定点组合器(Y可以,但它不是唯一的定点组合器)。\n首先,关于我在下面使用的符号:(iszero采用 Church 数字,检查它是否为零并返回 Church 布尔值),T(Church 编码的真布尔值),pred(Church 数字的前驱函数)和Y(a定点组合器)。
let TRUE = Y (\xce\xbbr. \xce\xbbn. (iszero n) T (\xce\xbbx. (r (pred n))))\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,这let不是 lambda 演算语法的一部分,它是为我们引入名称的元语法。
其工作原理如下:Y 将参数转换r为“self”——当函数调用时,r它会调用自身。为了说明这一点,我将把上面的内容重写为递归形式(警告:这只是为了说明目的,lambda 演算不允许这样做;因为所有函数都是匿名的,你不能使用它们的函数来调用它们名称——这是没有办法的):
let TRUE = \xce\xbbn. (iszero n) T (\xce\xbbx. (TRUE (pred n)))\nRun Code Online (Sandbox Code Playgroud)\n\n我已经剥离了该\xce\xbbr.部分并替换r为TRUE(再次强调,请不要在作业中这样做,它不是有效的 lambda 演算)。
而且这个定义更容易理解:如果TRUE像这样调用TRUE 0它只会返回T,否则它返回一个只有一个参数的函数,该函数包装了一个包含 (n - 1) 个参数的函数,本质上代表了一个包含 n 个参数的函数。
至于你关于工具的问题:一种方法是使用Scheme/Racket——它将有助于检查你的“lambda演算代码”是否正常运行。例如,下面是TRUERacket 中的一个实现:
(define (Y f)\n ((lambda (x) (x x))\n (lambda (x) (lambda (a) ((f (x x)) a)))))\n\n(define TRUE\n (Y (lambda (r)\n (lambda (n)\n (if (zero? n)\n #t\n (lambda (x) (r (sub1 n))))))))\n\n;; tests\n> (TRUE 0)\n#t\n> ((TRUE 1) #f)\n#t\n> (((TRUE 2) #f) #f)\n#t\n> ((((((TRUE 5) #f) #f) #f) #f) #f)\n#t\nRun Code Online (Sandbox Code Playgroud)\n\n我应该补充一点,我在这里使用内置布尔值、整数、if 表达式、sub1,zero?而不是 Church 编码的值。否则会使这个例子变得更大(或不完整)。