Y组合子:\f.(\x.f(xx))(\x.f(xx)),接受一个函数,返回一个高阶函数

Y组合子用于生成匿名递归函数。

什么叫匿名递归函数,考虑以下C语言递归函数

int sum(int n)
{
return n == 0 ? 0 : n + sum(n-1);
}

这个函数在内部递归调用了自身,调用自身需要函数本体的名字,这个函数叫sum,sum内部用名字sum,递归调用了自己

在lambda演算中,可以写成类似的表达式sum = \x. x == 0 ? 0 : sum x

但是对于一个lambda表达式,他本身是匿名的,lambda在定义的过程中引用了自身,就算是C++,这样的lambda表达式也是不成立的

auto sum = [](int n) {
return n == 0 ? 0 : n + sum(n-1);
};

lambda表达式本身是不具名的,我们需要绕开这个限制。

一种可能的解决办法是使用高阶函数,用另一个函数把上面的sum包装一下:它接受一个函数f,并返回一个函数,这个函数接受x,判断递归终点,或调用f继续递归:

G = \f. \x. x == 0 ? 0 : f (x-1)

写成C++是这样的

auto G = [](function<int(int)> f) {
return [&](int x) {
return x == 0 ? : 0 : x + f(x-1);
};
};

现在我们发现,当有一个函数f使得G(f) = [](int x){return x == 0 ? 0 : x + f(x-1);} = f的时候,这个f正好是我们需要的匿名递归函数sum

G(f) = f,眼熟吗,还记得不动点这个概念吗,我们需要的匿名递归函数sum就是函数G的不动点

求解这个不动点sum,我们即可获得一个匿名递归函数,如何求解见附

最后的结果:sum = YG,Y和G前面已知,这样,sum是一个签名为int(int)的函数,是一个匿名递归函数

Y组合子也称不动点组合子,用这个方法可以求解一切匿名递归函数。

附:sum = YG使得G(sum) = sum的证明:

证明:对于任意G,G(YG) = YG

令W = \x. G(xx), X = WW //这个令真的太TM绝了,反正我是没想到

有X = WW = (\x. G(xx))W = G(WW) = G(X)

又因为YG = (\x. G(xx))(\x. G(xx)) = WW = X

所以G(X) = X就是G(YG) = YG

证毕

Lambda演算 - 简述Y组合子的作用的更多相关文章

  1. Y组合子

    Y组合子 Y组合子的用处 作者:王霄池链接:https://www.zhihu.com/question/21099081/answer/18830200来源:知乎著作权归作者所有.商业转载请联系作者 ...

  2. 大到可以小说的Y组合子(二)

    问:上一回,你在最后曾提到"抽象性不足",这话怎么说? 答:试想,如果现在需要实现一个其它的递归(比如:Fibonacci),就必须把之前的模式从头套一遍,然后通过fib_make ...

  3. Racket中使用Y组合子

    关于Y组合子,网上已经介绍很多了,其作用主要是解决匿名lambda的递归调用自己. 首先我们来看直观的递归lambda定义, 假设要定义阶乘的lambda表达,C#中需要这么定义 Func<in ...

  4. 大到可以小说的Y组合子(一)

    问:上回乱扯淡了一通,这回该讲正题了吧. 答:OK. 先来列举一些我参考过,并从中受到启发的文章. (1.)老赵的一篇文章:使用Lambda表达式编写递归函数 (2.)装配脑袋的两篇文章:VS2008 ...

  5. 大到可以小说的Y组合子(三)

    答:关于Fix的问题你fix了吗? 问:慢着,让我想想,上次留下个什么问题来着?是说我们有了一个求不动点的函数Fix,但Fix却是显式递归的,是吧? 答:有劳你还记的这个问题. 问:Fix的参与背离了 ...

  6. 大到可以小说的Y组合子(零)

    问:啊!我想要一个匿名的递归… 答:Y(音同Why)… … … 问:作为一位命令式语言的使用者,为什么会突然折腾起Y组合子呢? 答:的确,这事儿要从很久以前的几次搁浅开始说起…上学的时候,从来没有接触 ...

  7. 简单易懂的程序语言入门小册子(4):基于文本替换的解释器,递归,如何构造递归函数,Y组合子

    递归.哦,递归. 递归在计算机科学中的重要性不言而喻. 递归就像女人,即令人烦恼,又无法抛弃. 先上个例子,这个例子里的函数double输入一个非负整数$n$,输出$2n$. \[ {double} ...

  8. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  9. [学习] 从 函数式编程 到 lambda演算 到 函数的本质 到 组合子逻辑

    函数式编程 阮一峰 <函数式编程初探>,阮一峰是<黑客与画家>的译者. wiki <函数编程语言> 一本好书,<计算机程序的构造与解释>有讲到schem ...

随机推荐

  1. Android 中onSaveInstanceState和onRestoreInstanceState学习

    1. 基本作用: Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate().onPaus ...

  2. Linux标准出错重定向导出

    ~$ ls han >1.txt 2>&1

  3. QT显示歌词渐变

    central = new QWidget(this); setCentralWidget(central); central->setAutoFillBackground(true); cen ...

  4. 1-Spark高级数据分析-第一章 大数据分析

    1.1 数据科学面临的挑战 第一,成功的分析中绝大部分工作是数据预处理. 第二,迭代与数据科学紧密相关.建模和分析经常需要对一个数据集进行多次遍历.这其中一方面是由机器学习算法和统计过程本身造成的. ...

  5. 关于MySQL数据导出导入

    工具 mysqlmysqldump 应用举例 导出 导出全库备份到本地的目录 mysqldump -u$USER -p$PASSWD -h127.0.0.1 -P3306 --routines --d ...

  6. Repeater 根据某一列的值加颜色

    //排队中 protected void rptOrdersList_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterIt ...

  7. GitHub的用法:到GitHub上部署项目

    先提供两个较好的Git教程: 1. 如何在github部署项目: lhttp://jingyan.baidu.com/article/656db918fbf70ce381249c15.html 2. ...

  8. 个人项目(JUnit单元测试)

    ---恢复内容开始--- 一.             题目简介 这次的单元测试我选择作了一个基本运算的程序,该程序实现了加,减,乘,除,平方,倒数的运算,该程序进行测试比较的简单,对于初步接触JUn ...

  9. Pattern Recognition And Machine Learning (模式识别与机器学习) 笔记 (1)

    By Yunduan Cui 这是我自己的PRML学习笔记,目前持续更新中. 第二章 Probability Distributions 概率分布 本章介绍了书中要用到的概率分布模型,是之后章节的基础 ...

  10. rsync+inotify实现自动备份

    1.rsync命令 文件在不同服务器之间备份,有两种方式,一种是推,另一种是拉 推:即由主服务器推送数据到次服务器 拉:即由次服务器向主服务器要数据 一般采用拉的方式 但是这样同时多服务器备份就会分享 ...