我正在尝试在纯lambda演算中构建列表(实际上二进制树伪装成列表(以[Root, [Left SubTree], [Right SubTree]]
的形式),但出于这个特定问题的目的,我们可以讨论lambda中的一般列表演算)。
lambda演算的一些基本定义(用Racket语法表示)我将在这个问题中使用:
(define true (lambda (x) (lambda (y) x)))
(define false (lambda (x) (lambda (y) y)))
(define if (lambda (x) (lambda (y) (lambda (z) ((x y) z)))))
; I'm using Parigot Encodings to represent numbers
(define zero (lambda (s) (lambda (z) z)))
(define one (lambda (s) (lambda (z) ((s zero) z))))
(define two (lambda (s) (lambda (z) ((s one) ((s zero) z)))))
; Here are some converter functions for debugging/printing
(define (p->int n)
((n (lambda(x) add1)) 0))
(define (int->p i)
(if (zero? i)
(lambda (f) (lambda (x) x))
(let ((m (int->p (- i 1))))
(lambda (f) (lambda (x) ((m f) ((f m) x)))) )))
; Building blocks for Lists. A list consists of a single element Head,
; followed by the rest of the list (Tail). Lists are thus recursively
; defined. An empty list consists of only the element 'nil'
(define mkpair (lambda (a) (lambda (b) (lambda (c) ((c a) b)))))
(define Head (lambda (p) (p true)))
(define Tail (lambda (p) (p false)))
(define nil false)
对于在此类列表上操作,我需要检测列表何时为空(例如,在二进制搜索树上进行二进制搜索时检测叶节点,表示为列表)。以下link将该函数指定为isempty = λl.l(λab.false)true
,我在Racket中定义如下:
(define Null? (lambda (p) (p (lambda (x) (lambda (y) false)))true))
这看起来很有效,如下所示:
(p->int (((if (Null? (Head ((mkpair nil) one)))) two) one))
简而言之,上面的应用程序检查列表[nil, one]
的头部是否为空列表(仅包含nil
),如果是,则评估为two
,当它被馈送时转换器函数p->int
,生成2
。除了Null?
函数之外,所有好处似乎都不会评估为false
,如下面的代码段所示:
(p->int (((if (Null? (Tail ((mkpair nil) one)))) two) one))
其中也评估为Racket中的2
。
有人可以在我的错误中指出我,我希望这是一些我无法察觉的语法!
PS:为了防止我完全接近这个错误的方式,我试图在Racket的纯lambda演算中实现二进制搜索树。任何指向我最终目标的指针都会非常感激 - 我已经列出了我采取的一种方法。(有关我正在尝试模拟的函数的一些额外阅读,请参阅this)。
答案 0 :(得分:1)
问题实际上是isempty
函数的错误转置。你应该写:
(define Null? (lambda (p) ((p (lambda (x) (lambda (y) false))) true)))
而不是:
(define Null? (lambda (p) (p (lambda (x) (lambda (y) false))) true))
因为λl.l(λab.false)true
应解释为:
λl. ((l (λab.false)) true)
虽然你的解释在lambda演算中没有对应关系。