先了解下相关的知识点(以下都只用先了解简单的概念,建议wiki):

BNF范式,上下文无关文法,函数柯里化。

lambda读书笔记演算:

http://www.blogjava.net/wxb_nudt/archive/2005/05/15/4311.aspx

lambda演算实例

关于lambda演算的定义和解释的确有点让人迷糊,主要不是因为lambda演算有多复杂,而是一些基本概念没有归入正确位置的原因。

这里先写一点草稿,在实践中学习和领悟lambda演算到底是个什么东西。

一:自然数运算:

在lambda演算中的邱奇数定义
0 = λf.λx.x
1 = λf.λx.f x
2 = λf.λx.f (f x)
3 = λf.λx.f (f (f x))

SUCC = λn.λf.λx.f(n f x)

SUCC是一个有三个自由变量的函数

计算
SUCC 0
=λn.λf.λx.f (n f x) 0 //将0代入n
=λf.λx.f (0 f x) //0=λf.λx.x
=λf.λx.f (λf.λx.x f x) //λf.λx.x f x是将两个参数的函数λf.λx.x应用于(f x)这两个值的结果,结果等于x
=λf.λx.f x //正好等于1的邱奇数定义

SUCC 1
=λn.λf.λx.f (n f x) 1 //将1代入n
=λf.λx.f (1 f x) //0=λf.λx.x
=λf.λx.f (λf.λx.(f x) f x) //λf.λx.(f x) f x是将两个参数的函数λf.λx.(f x)应用于(f x)这两个值的结果,结果等于(f x)
=λf.λx.f (f x) //正好等于2的邱奇数定义

小节:
不妨把lambda演算看做一个自动机,你输入一个式子(一个λ项),它就给你输出一个演算结果,至于输入和输出有什么意义,是我们自己赋予的。

比如为了计算0的后继,我们只是输入(λn.λf.λx.f(n f x) λf.λx.x)给这个机器,这个机器就会给我们输出λf.λx.f x。在解释这个输入输出关系时,我们会说,SUCC 0 = 1,这样就赋予这个运算一个意义。这个自动机知道自己在做加1操作吗?其实它什么也不知道。

为什么邱奇数这样定义?其实不妨把它们看做是被偶然发现的一些λ项,这些λ项的组合项的演算结果恰好能对应于自然数的运算而已。定义自然数还有别的定义方式,邱奇数及对应的运算符只是其中的一种而已。

比如我们又发现一个λ项PLUS
PLUS = λm.λn.λf.λx.m f (n f x)
先不要管什么意义,试试下面这个组合起来的λ项

PLUS 2 3
= λm.λn.λf.λx.m f (n f x) 2 3 //将3和2应用于m,n这两个自由变量上
=λf.λx.3 f (2 f x) //(2 f x) = (λf.λx.(f (f x)) f x) = f (f x)
=λf.λx.3 f (f (f x)) //3=λf.λx.f (f (f x))
=λf.λx.(λf.λx.f (f (f x)))) f (f (f x)) //将f 和 (f (f x)) 应用于f和x这两个自由变量上
=λf.λx.f (f (f (f (f x)))) //我们发现正好等于5的邱奇数定义

很奇妙的性质,我们用PLUS(λm.λn.λf.λx.m f (n f x) )这样的λ项作用于代表2和3的邱奇数时,得到的演算结果恰恰是代表5的邱奇数。

此外,还可以构造出乘法和除法等各种运算符。

二、逻辑运算:

TRUE := λx y.x
FALSE := λx y.y
AND := λp q.p q FALSE
OR := λp q.p TRUE q
NOT := λp.p FALSE TRUE
IFTHENELSE := λp x y.p x y

需要重复加以强调的是,这些λ项都是一些构造,我们构造它们的原因是,这些项的组合所得到的演算结果恰恰符合我们对逻辑运算的认识,所以我们才赋予它们以逻辑运算符的意义,也正因为这些构造,我们才可以让那个演算自动机代替我们去做各种逻辑运算。

计算:

AND TRUE TRUE
=λp q.p q FALSE (TRUE TRUE)//用TRUE和FALSE替换自由变量p和q
=TRUE TRUE FALSE //TRUE = λx y.x
=λx y.x (TRUE FALSE) //用TRUE和FALSE替换自由变量x和y
=TRUE //y没有在函数体中出现,所以等于TRUE

三、有序对
CONS := λx y.λp.IF p x y
CAR := λx.x TRUE
CDR := λx.x FALSE

这里很有趣的一点是,和lisp的实现对照,我们发现car和cdr是在lisp的基本运算符中的,但实际上,它们仍然可以用λ项来表示。

我们先构造一个有序对
CONS m1 m2
=λx y.λp.IF p x y (m1 m2) //很简单,用m1和m2替换x和y就行了
=λp.IF p m1 m2

然后计算这个有序对的CAR
CAR (IF p m1 m2)
=λx.(x TRUE) (λp.IF p m1 m2) //x用(λp.IF p m1 m2)替换
=(λp.IF p m1 m2) TRUE //p用TRUE替换
=IF TRUE m1 m2 //根据IF的含义我们知道结果就是m1
=m1

CDR (IF p m1 m2)
= λx.x FALSE (λp.IF p m1 m2)
=(λp.IF p m1 m2) FALSE
=IF FALSE m1 m2
=m2

四、Y不动点

考虑一下这台λ演算自动机,它再简单不过了,只是按照非常简单的规则应用函数,将值绑定到自由变量,然后继续演算,直到最终结果。

在开始计算时,我们输入的都是长长的λ项,甚至连SUCC,CDR这些简写都没有,比如要做一个2+3的加法,我们会输入 λm.λn.λf.λx.m f (n f x) (λf.λx.f (f x)) (λf.λx.f (f (f x))),然后这台演算自动机会给我们输出λf.λx.f (f (f (f (f x))))这个结果。

这样问题就来了,如果函数要递归调用自己,那该怎么办呢?在lambda演算中,无法定义包含自身的函数(虽然在lisp中可以)。
构造出这样一个Y
Y = λf.(λx.f(x x)) (λx.f(x x))
Y g
= (λf.(λx.f(x x))(λx.f(x x))) g //用g替换f
= λx.g(x x) (λx.g(x x)) //用λx.g(x x)替换x这个自由变量
= g (λx.g (x x) λx.g (x x)) //我们发现λx.g (x x) λx.g (x x)恰好等于Y g
= g (Y g)
继续
= g (λx.g (x x) λx.g (x x))
= g (g (λx.g (x x) λx.g (x x)))
= g (g (g (λx.g (x x) λx.g (x x))))
= ... ...

这里我们能看出来了,如果给这个演算自动机输入Y g,也就是实际上输入了这样一个λ项(λf.(λx.f(x x)) (λx.f(x x)) g)之后,演算自动机将不会停机,永远递归下去,直到耗尽所有内存。

从这里可以看出来,虽然lambda演算表面上不能自己调用自己,因为无法给自己起一个名字,但实际上可以构造出这样一个λ项,可以让计算递归下去。

接下来,看如何利用这一特殊的λ项的性质,来完成一些有用的计算:

计算阶乘的数学公式如下:
fact(n) = if n=0 then 1 else n * fact(n-1)

构造如下的λ项,计算5的阶乘,其中Y=λf.(λx.f(x x)) (λx.f(x x)),而g=λf n.(ISZERO n 1 MULT n·f(n-1)),都是λ项的形式。

(λn.(ISZERO n 1 (MULT n ((Y g)(n-1)))) 5
=
(按照维基百科上的计算过程,改写为容易懂的if then else形式)

if 5 = 0 then 1 else 5·(g(Y g,5-1))
5·(g(Y g)4)
5·(λn.(if n = 0 then 1 else n·((Y g)(n-1))) 4)
5·(if 4 = 0 then 1 else 4·(g(Y g,4-1)))
5·(4·(g(Y g)3))
5·(4·(λn.(if n = 0 then 1 else n·((Y g)(n-1))) 3))
5·(4·(if 3 = 0 then 1 else 3·(g(Y g,3-1))))
5·(4·(3·(g(Y g)2)))

lambda演算的更多相关文章

  1. Lambda演算 - 简述Y组合子的作用

    Y组合子:\f.(\x.f(xx))(\x.f(xx)),接受一个函数,返回一个高阶函数 Y组合子用于生成匿名递归函数. 什么叫匿名递归函数,考虑以下C语言递归函数 int sum(int n) { ...

  2. 简单易懂的程序语言入门小册子(1.5):基于文本替换的解释器,递归定义与lambda演算的一些额外说明

    这一篇接在第一篇lambda演算的后面.讲讲一些数学知识. 经常有些看似很容易理解的东西,一旦要描述得准确无误,就会变得极为麻烦. 软件工程里也有类似情况:20%的代码实现了核心功能,剩下80%的代码 ...

  3. [摘录] 图灵机与lambda演算的关系

    在阅读函数式编程相关资料时,看到如下一段话.感觉说的很好,可以帮助我这种学渣一点点的建立起整个知识体系. 以下片段,摘抄自豆瓣网友 赛义甫 的豆列 “逻辑与计算” 中的一段介绍. 莱布尼兹曾经有两个梦 ...

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

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

  5. 简单易懂的程序语言入门小册子(1):基于文本替换的解释器,lambda演算

    最近比较闲,打算整理一下之前学习的关于程序语言的知识.主要的内容其实就是一边设计程序语言一边写解释器实现它.这些知识基本上来自Programming Languages and Lambda Calc ...

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

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

  7. Lambda演算(一)大道至简

    从选择信息专业开始到回炉读书为止,四舍五入码了八年代码.对于计算机科学的认知仅限于: 1)使用不同语言实现特定功能 2)实现不同算法以增进系统性能 3)搭建不同架构进行组织管理   但从未思考一些本质 ...

  8. 我的最爱Lambda演算——开篇

    (在这个帖子的原始版本里,我试图用一个JavaScript工具来生成MathML.但不太顺利:有几个浏览器没法正确的渲染,在RSS feed里也显示的不好.所以我只好从头开始,用简单的文本格式重新写一 ...

  9. C++ 泛型编程/模板 泛函编程/Lambda/λ演算

    1.泛型编程(C++模板) 其中,Ada, Delpha, Java, C#, Swift 称之为 泛型/generics; ML, Scala和 Haskell 称之为 参数多态/parametri ...

随机推荐

  1. 再造轮子之网易彩票-第一季(IOS 篇 by sixleaves)

    前言 在网上看了别人做的模仿网易彩票的项目, 于是也跟着用自己的想法做了一篇.写这篇博客的目的, 在于UI综合的一次小练习, 同时总结和串联其各个控件之间的应用.封装思想等.考虑到有人上不了githu ...

  2. nodejs学习笔记之包、模块实现

        简单了解了node的安装和一些基本的常识之后,今天学习了node中很重要的包和模块的一些知识点.       首先学习一下包的规范,它由包结构和包描述两部分组成.包结构用于组织包的各种文件,包 ...

  3. Objective-C中NSString和NSMutableString的基本用法

    int main(int argc, const char * argv[]) { @autoreleasepool { //----------------NSString------------- ...

  4. JAX-WS 学习二:基于WEB容器,发布WebService

    WebService 的发布通过调用 Endpoint.publish() 方法来启动一个java内嵌的WEB容器来实现的,如果要将WebService部署到一个WEB容器中去,需要使用jax-ws提 ...

  5. C# 二叉堆

    二叉堆数据结构讲解: http://www.cnblogs.com/yc_sunniwell/archive/2010/06/28/1766751.html   C#代码实现 using System ...

  6. ios实现程序切入后台,实现后台任务

    首先,iOS 会再持续切入后台,给我们5秒钟的时间去处理相关数据,5秒后,程序不会再执行任何代码,处于挂起状态. // 项目需求,按下Home切换后台后向服务器传一些数据,废话不多说,直接上代码 /* ...

  7. python学习之路-8 面向对象之进阶

    上篇内容回顾和补充 面向对象三大特性 封装 继承 多态 在python中没有多态的概念 变量的类型允许为多种数据类型称之为多态 # c#/java中的多态 # 伪代码 def func(int arg ...

  8. Scala-Partial Functions(偏函数)

    如果你想定义一个函数,而让它只接受和处理其参数定义域范围内的子集,对于这个参数范围外的参数则抛出异常,这样的函数就是偏函数(顾名思异就是这个函数只处理传入来的部分参数). 偏函数是个特质其的类型为Pa ...

  9. 2014 (多校)1011 ZCC Loves Codefires

    自从做了多校,整个人都不好了,老是被高中生就算了,题老是都不懂=-=原谅我是个菜鸟,原谅我智力不行.唯一的水题. Problem Description Though ZCC has many Fan ...

  10. Unity 读取CSV与Excel

    前几天看到我们在游戏中需要动态加载某些角色的游戏策划值,关于这个问题怎么解决呢?其实办法很多种,归根到底,就是数据的读取.我们可以想到的存储数据的载体有很多.例如:txt,xml,csv,excel. ...