;; 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的公式。我怎么能记住它,并在我使用它之后很久就重现它?
答案 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)))