Y-Combinator实例

时间:2009-05-15 15:54:15

标签: functional-programming y-combinator

我最近一直在阅读有关函数式编程的内容,我正试图找到Y-Combinator。我知道您可以使用Y-Combinator以不直接支持递归的语言有效地实现递归。但是,我可能使用的每种语言都支持递归,所以我不确定使用Y-Combinator会有多大用处。

我缺少一个更好的Y-Combinator使用实例吗?有没有人真正在实际生产代码中使用过一个?或者使用Y-Combinator真的只是一个令人费解的学术练习(尽管很酷)。

5 个答案:

答案 0 :(得分:27)

我不同意其他答案:定点(Y)组合器确实具有实际应用,但找到它们需要非常富有想象力的头脑。像布鲁斯麦克亚当。这是他的论文That About Wraps it Up中的摘要:

  

用于计算固定点的Y组合器可以用标准ML表示。它经常被用作高阶函数的幂的一个例子,但通常不被认为是有用的编程结构。在这里,我们看看基于Y组合器和包装器的编程技术如何能够为程序员提供对函数内部工作的一定程度的控制,否则可能无需重写和重新编译代码。作为实验,使用该技术实现类型推断算法W,从而产生对算法具有最小干扰的错误消息。此示例程序的代码说明了概念的真正有用性以及它们的易用性。还讨论了许多其他实现技术和可能的应用程序,包括使用高阶函数来模拟异常和延续的使用。

这是一篇很棒的论文;任何对函数式编程感兴趣的人都可能喜欢阅读它。

答案 1 :(得分:7)

你可以查看这篇关于在C#中实现Y Combinator的好文章:Recursive Lambda Expressions,它可能会帮助你更好地理解这个想法。

您可能想查看维基百科上的一些好文章:Fixed point combinatorFixed point theorems

正如内森所说,许多功能技术与Y组合器有关并且很有用,所以请坚持下去! Y真的很有用,因为它可以让你更好地理解你的代码,但我不认为这对描述它的帮助特别有帮助。

答案 2 :(得分:4)

您可以将组合子视为运行您的函数的虚拟机,您可以通过非递归函数(=高阶函数)来描述它。

有时将这个组合器置于程序控制之下会很好,就像面向方面的编程(memoizing,tracing,...)那样,但是我知道的编程语言不允许这样做。可能在大多数时候太麻烦和/或太难学习。

答案 3 :(得分:3)

如果我错了,其他人可以纠正我,但我很确定Y组合器是严格的学术性的。想一想:要实现它,你的语言需要支持高阶函数而不是递归。我只知道一种语言:lambda calculus。

因此,在我们的机器从图灵机转换到运行lambda演算之前,Y组合器将严格学术化。

注意:与Y组合器相关的其他功能技术非常有用,所以请继续使用。理解Y组合子将帮助您理解延续,懒惰评估等。

答案 4 :(得分:1)

let sprite = pipe4 sprite_start blanks (manyTill attribute newline) blanks (fun a b c _ -> Sprite(a,c))

let sprites = 
    let rec y f x = f (y f) x // The Y Combinator
    //let rec sprites_up = many1Indents sprite sprites_up |>> (fun x -> SubSprites x) // Does not work.
    let sprites_up = y (fun f -> many1Indents sprite f |>> (fun x -> SubSprites x))
    many1Indents sprite sprites_up

以下是我在F#中制作的小型游戏库的编译器示例。更具体地说,在上面我需要sprites_up以递归方式调用自身,否则缩进解析器将无法正常工作。

没有Y Combinator,我无法正确完成解析器,并且不得不求助于编写这样的东西:

let sprites_up4 = many1Indents sprite error |>> (fun x -> SubSprites x) 
let sprites_up3 = many1Indents sprite sprites_up4 |>> (fun x -> SubSprites x) 
let sprites_up2 = many1Indents sprite sprites_up3 |>> (fun x -> SubSprites x) 
let sprites_up1 = many1Indents sprite sprites_up2 |>> (fun x -> SubSprites x) 
let sprites_up = many1Indents sprite sprites_up1 |>> (fun x -> SubSprites x) 

不会是一个很好的解决方案,Y Combinator真的救了我。这当然不是第一个想到的东西。