lisp中的定点组合子

时间:2012-10-28 22:09:19

标签: lisp scheme combinators y-combinator

;; compute the max of a list of integers

(define Y
  (lambda (w)
    ((lambda (f)
       (f f))
     (lambda (f)
       (w (lambda (x)
            ((f f) x)))))))

((Y
  (lambda (max)
    (lambda (l)
      (cond ((null? l) -1)
            ((> (car l) (max (cdr l))) (car l))
            (else (max (cdr l)))))))
 '(1 2 3 4 5))

我希望了解这种结构。有人能为这段代码提供清晰简单的解释吗?

例如,假设我忘记了Y的公式。我怎么能记住它,并在我使用它之后很久就重现它?

2 个答案:

答案 0 :(得分:2)

到目前为止我发现的最好的解释是在"The Little Schemer"第9章中。整章逐步解释了Y-Combinator的工作原理,以及如何从一个组合开始。任意递归程序。

答案 1 :(得分:2)

这里有一些相关的答案(由我):

基本上,将 Y 定义为λr.(λh.h h) (λg.r (λx.(g g) x)),应用程序Y r会缩减为

Y r
(λw.(λh.h h) (λg.w (λx.(g g) x))) r
(λh.h h) (λg.r (λx.(g g) x))
h h
    ;where
        h = (λg.r (λx.(g g) x))       <----\
                                           |
(λg.r (λx.(g g) x)) h                      |
r (λx.(g g) x)             <-------------- | ----------\
    ;where                                 |           |
        g = h                         -----/           |
        ;so that                                       |
        (g g) = (h h) = r (λx.(g g) x)           ------/

所以r必须要有两个参数 - 首先表示要调用的递归函数,第二个 - 实际参数:

        r = λf (λx. ....x.....(f y)...... )

以便(Y r) x缩小为

(r (λx.(g g) x)) x
(r f) x
    ;where
        f   = (λx.(g g) x) 
        f y = (λx.(g g) x) y = (g g) y = (r f) y  ; f is "fixed point" of r

定义f = (λx.(g g) x)表示,在调用f y时,将调用(g g) y此时 g将自行应用,r&#34;拉&#34;来自g内部,(r f)的结果使用y参数调用。即由(f y)应用程序生成的lambda表达式主体中的任何调用(r f)都会被转换回(r f) y,即使用新参数y调用同一个主体。

重要的实现细节是它是相同的函数体,还是它的 copy ,但语义是相同的 - 我们能够进入相同的函数体使用新的参数值。

Y组合子的本质是通过引用和自我应用进行复制:我们通过相同的 name 引用相同的东西,两次;因此我们安排 it 接收本身作为参数。

当没有引用时,如纯lambda演算,参数接收参数的文本副本 - 即通过文本重写进行缩减 - 这仍然有效,因为相同的副本被复制并且传递,作为自我的参数被馈送,因此如果需要,它可以在下一次迭代中使用。

但是,当共享引用可用时(同名的所有使用都引用同样的事情),它会更有效率。在评估环境模型下,自引用函数的创建很简单

(let ((fact #f)) 
  (set! fact 
        (lambda (n) (if (< 2 n) 1 
                               (* n (fact (- n 1)))))) 
  fact)

事实上,你的答案中的定义是应用顺序Y组合子。使用正常顺序,可以应用eta减少而不会导致无限循环,以获得Ynorm = (λw.(λh.h h) (λg.w (g g))),其被规范地写为

Ynorm = (λf.(λx.f (x x)) (λx.f (x x)))

确实

Ynorm g
= (λx.g (x x)) (λx.g (x x))
= g ((λx.g (x x)) (λx.g (x x)))