【问题标题】:Y-Combinator Practical ExampleY-Combinator 实际示例
【发布时间】:2009-05-15 15:54:14
【问题描述】:

我最近读了一些关于函数式编程的书,我正在尝试了解 Y-Combinator。我知道您可以使用 Y-Combinator 以不直接支持递归的语言有效地实现递归。但是,我可能使用的每种语言都已经支持递归,所以我不确定使用 Y-Combinator 会有多大用处。

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

【问题讨论】:

    标签: functional-programming y-combinator


    【解决方案1】:

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

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

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

    【讨论】:

    • 你能举一个例子吗?我得到“请求的资源()不可用。”当我尝试下载它时。
    • 我已将链接替换为爱丁堡网站的链接;论文版本可能较旧,但我已验证您可以下载 PDF。
    • 谢谢!我一定会看看这个。
    【解决方案2】:

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

    您可能想在 Wikipedia 上查看一些不错的文章:Fixed point combinatorFixed point theorems

    正如 Nathan 所说,许多函数技术都与 Y 组合器相关并且很有用,所以坚持下去! Y 确实很有用,因为它可以让您更好地理解您的代码,但我认为描述它的帮助并不是特别有帮助。

    【讨论】:

      【解决方案3】:

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

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

      注意:与 Y 组合器相关的其他函数式技术也很有用,所以请坚持下去。了解 Y 组合器将帮助您了解延续、惰性求值等。

      【讨论】:

      • 内森,我认为你错了,所以我试图纠正你:-)
      • C# 不支持 lambda 表达式中的递归 - 因此可以使用 Y 组合器来实现它。
      • “所以在我们的机器从图灵机切换到在 lambda 演算上运行之前,Y 组合器将是严格的学术性的。” Lambda 演算实际上是图灵完备的。见en.wikipedia.org/wiki/Turing_completeness
      • @JPCosta:是的,但这是学术观点。图灵机和 lambda 演算是等价的,但我们今天拥有的计算机是图灵机。如果您需要在 lambda 演算上实现递归,那么 Y 组合器的知识突然变得实际上很重要。 (当然,Norman Ramsey 的例子也很有用,适用于现在的电脑开机。)
      【解决方案4】:

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

      有时让这个组合器在程序控制下会很好,可以做与面向方面编程(记忆、跟踪等)类似的事情,但我所知道的任何编程语言都不允许这样做。可能大部分时间太麻烦和/或太难学习。

      【讨论】:

        【解决方案5】:
        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 确实救了我。不过,这肯定不是首先想到的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多