【问题标题】:Is the Y Combinator a left fold or a right fold?Y Combinator 是左折叠还是右折叠?
【发布时间】:2020-05-04 07:32:01
【问题描述】:

Y 组合子(来自wikipedia article)定义为:

Y = \f.(\x.f(x x)) (\x.f(x x))

所以当我们在 g 上调用 Y 时:

Y g = (\f.(\x.f(x x)) (\x.f(x x))) g 

= (\x.g(x x)) (\x.g(x x))

= g((\x.g(x x)) (\x.g(x x)))

= g (Y g)

重复导致:

Y g = g(Y g) = g(g(Y g)) = g(...g(Y g)...)

因为这个展开是在一元函数之上的,所以我不知道这是左折叠还是右折叠。

我对左折叠的理解是它类似于这个(带有二元函数 f):

f (f (f (f 1 2) 3) 4) 5)

而对二元函数 f 的右折叠如下所示:

f 1 (f 2 (f 3 (f 4 5)))

我想任何一元函数,然而,看起来与左折叠或右折叠扩展相同:

f (f (f (f (f x))))

这是正确的吗?如果不是,Y 组合器是展开成左折叠还是右折叠?

【问题讨论】:

    标签: recursion functional-programming fold lambda-calculus y-combinator


    【解决方案1】:

    Y 这样的定点组合器仅启用匿名递归。你用这个递归做什么完全取决于你。您可以使用它定义左关联折叠和右关联折叠。我希望你不介意我用 Javascript 说明这一点:

    // simplified Y combinator with eta abstraction due to eager evaluation
    
    const fix = f => x => f(fix(f)) (x);
    
    // left fold
    
    const foldl = fix(rec => f => acc => ([x, ...xs]) =>
      x === undefined
        ? acc
        : rec(f) (f(acc) (x)) (xs));
        
    // right fold
    
    const foldr = fix(rec => f => acc => ([x, ...xs]) =>
      x === undefined
        ? acc
        : f(x) (rec(f) (acc) (xs)));
        
        
     console.log(
       foldl(x => y => x - y) (0) ([1,2,3])); // -6
       
      console.log(
       foldr(x => y => x - y) (0) ([1,2,3])); // 2

    【讨论】:

      猜你喜欢
      • 2014-09-03
      • 2017-04-11
      • 1970-01-01
      • 2015-04-12
      • 2013-04-13
      • 2011-11-15
      • 2013-06-28
      • 1970-01-01
      • 2013-11-13
      相关资源
      最近更新 更多