我无法理解的Y Combinator的,所以我想实现它,结束了东西短,这工作。 这怎么可能?(I

2019-07-04 17:13发布

我无法理解的Y组合子,所以我想实现一个启用递归没有本地实现的功能。 经过一番思考,我结束了这一点:

Y = λx.(λv.(x x) v)

这是比实际更短:

Y = λf.(λx.f (x x)) (λx.f (x x))

而且,对于我吃惊的是,工作。 一些例子:

// JavaScript
Y = function(x){
  return function(v){
    return x(x, v);
  };
};
sum = Y(function(f, n){
  return n == 0 ? 0 : n + f(f, n - 1);
});
sum(4);

; Scheme
(define Y (lambda (x) (lambda (v) (x x v))))
(define sum (Y 
    (lambda (f n) 
        (if (equal? n 0) 
            0 
            (+ n (f f (- n 1)))))))
(sum 4)

两个片段输出10(求和从0到4)如预期。

这是什么,为什么它是短,为什么我们喜欢更长的版本?

Answer 1:

它之所以是较短的是,你实现什么 Y组合。 这件事情,是实际的Y组合,以及东西有时被称为U形组合子之间。 要成为一个适当的Y组合,这应该工作:

(define sum
  (Y (lambda (f)
       (lambda (v) (if (equal? n 0) 0 (+ n (f (- n 1))))))))

或在Javascript:

sum = Y( function(f) { return function(n) {
  return n == 0 ? 0 : n + f(n-1);
};});

如果你用自己的方式工作,这是令工作,你会发现一两件事,这将使它不再是你需要移动复制f东西进入Y,这使得接下来的事情它甚至更长的时间是当你最终保护xx自应用程序的功能里面,因为这些语言都是严格。



Answer 2:

从“真正的”版本不同的是,你需要通过自己的函数中的参数,你通常不需要沿 - Y上给你的函数本身的recursice变种做了抽象。

点心在JavaScript中应该是公正

Y (function(rec){ return function (n) { return n==0 ? 0 : n + rec(n-1); };})

我明白了Y组合时我重组了共同JS表达至

function Y (f) {
    function alt (x) {
        function rec (y) { // this function is basically equal to Y (f)
             return x(x)(y); // as x === alt
        }
        return f (rec);
    }
    return alt(alt);
}


文章来源: I couldn't understand the Y-Combinator, so I tried to implement it and ended up with something shorter, which worked. How is that possible?