Lambda演算 Lambda Calculus 的简单理解

Lambda演算

在λ演算中,每个表达式都代表一个函数,这个函数有一个参数,并且返回一个值。不论是参数和返回值,也都是一个单参的函数。可以这么说,λ演算中,只有一种“类型”,那就是这种单参函数。

函数是通过λ表达式匿名地定义的,这个表达式说明了此函数将对其参数进行什么操作。例如,“加2”函数f(x)= x + 2可以用lambda演算表示为λx.x + 2 (或者λy.y + 2,参数的取名无关紧要)而f(3)的值可以写作(λx.x + 2) 3。函数的应用(application)是左结合的:f x y =(f x) y。

考虑这么一个函数:它把一个函数作为参数,这个函数将被作用在3上:λf.f 3。如果把这个(用函数作参数的)函数作用于我们先前的“加2”函数上:(λf.f 3)(λx.x+2),则明显地,下述三个表达式:

(λf.f 3)(λx.x+2) 与 (λx.x + 2) 3 与 3 + 2

是等价的。用js代码表达如下,

function f1(f) {
    return  f(3)
}

function f2() {
    return function (x) {
        return  x + 2;
    }
}

console.log(f1(f2()))

//=============或像下面这样写
console.log(f1((function () {
    return function (x) {
        return x + 2;
    }
})()));

有两个参数的函数可以通过lambda演算这么表达:一个单一参数的函数的返回值又是一个单一参数的函数(参见Currying)。例如,函数f(x, y) = x - y可以写作λx.λy.x - y。下述三个表达式:

(λx.λy.x - y) 7 2 与 (λy.7 - y) 2 与 7 - 2

也是等价的。js的代码表达如下,

//最普通的实现两个数相加的函数
function add0(x, y) {
    return x + y;
}

//使用函数的柯里化实现两个数相加
//也是js的闭包
function add1(num) {
    return function (numOther) {
        return num + numOther;
    }
}

console.log(add1(3)(2))

然而这种lambda表达式之间的等价性无法找到一个通用的函数来判定。

并非所有的lambda表达式都可以规约至上述那样的确定值,考虑

(λx.x x)(λx.x x)

(λx.x x x)(λx.x x x)

然后试图把第一个函数作用在它的参数上。 (λx.x x)被称为ω 组合子,((λx.x x)(λx.x x))被称为Ω,而((λx.x x x) (λx.x x x))被称为Ω2,以此类推。

若仅形式化函数作用的概念而不允许lambda表达式,就得到了组合子逻辑。

插播:关于λ项 

其实作为 Haskell 的核心,λ表达式是异常简洁的。下面是关于λ表达式 (λ Expression),也叫λ项 (λ Term) ,的定义:

  • 变元是λ项,通常用小写字母写出来,比如 x,y,z 等;
  • 如果 M 是λ项,那么 λx.M 也是;
  • 如果 M 和 N 都是λ项,那么 M N 也是。
  1. 变元 (variable) 形态的λ项很简单,就是 x 或者 y 或者 z 或者什么别的,我们通常用单个小写字母,有 时候也加上数字脚标,比如 x0, x1, x2 等,以示区分。
  2. 抽象 (abstraction) 形态的λ项,写出来就是先用λ这个符号本身作开头,后面跟一个变元,然后一个小点,然后跟一个任意的λ项。例如 λx.x 或 λx.y 或 λx.x x  等。
  3. 应用 (application) 形态的λ项,就是两个λ项写在一起,中间仅留一个空格做分隔。例如 f x 或者 x x。 写在前面的λ项通常叫函数(function),后面的叫参(argument)。比如在 x x 这个表达式里,就是把 x 这个函数作用于(apply to)它自己。

在实际书写抽象和应用两种λ项时,如果没有一定的标识,往往会产生歧义。所以通常是用括号来把一个λ项和它前后的符号区分开,比如 (λx.x) y 这个表达式,就是说函数 λx.x 作用在参数 y 上。 我们通常不认为括号本身是λ项的一部分,使用它们纯粹是为了书写。

括号的使用有时候也可以略去。约定俗成的习惯是在表达抽象时,小点后面整个式子(除非是遇到反括号) 都是与小点前面的变元对应的λ项。比如 λx.(λy.(x y)) 就可以简写为 λx.λy.x y;在表达应用时则向左结 合,比如 f x y 应该被理解为 (f x) y 而不是 f (x y)。

Lambda演算的语法

Lambda演算只有三类表达式:

  1. 函数定义:Lambda演算中的函数是一个表达式 ,写成:lambda x . body ,表示“一个参数参数为x的函数,它的返回值为body的计算结果”。 这时我们说:Lambda表达式绑定了参数 x
  2. 标识符引用(identifier reference):标识符引用就是一个名字,这个名字用于匹配函数表达式中的某个参数名
  3. 函数应用(function application):函数应用写成把函数值放到它的参数前面的形式,如(lambda x . plus x x) y 

Lambda 表达式 自由变量 和 闭合

A particular instance of a variable is “free” in a lambda expression if it is not “bound” by a lambda. For example, x is free in the expressions

x

and

λy. x

but not in this expression

λx. x

Because variables can be repeated, care must be taken to know which variable one is referring to.

For example, in this expression, the underlined occurrences of x are free, the others are not:

λy. x (λx. x x) x

A term is closed if it has no free variables; otherwise it is open

lambda表达式如果没有自由变量,那么其实闭合的。

自由标识符 vs. 绑定标识符

闭包(closure)或者叫完全绑定(complete binding)

在对一个Lambda演算表达式进行求值的时候,不能引用任何未绑定的标识符。

如果一个标识符是一个闭合Lambda表达式的参数,我们则称这个标识符是(被)绑定的;如果一个标识符在任何封闭上下文中都没有绑定,那么它被称为自由变量。

lambda x . plus x y:在这个表达式中,y和plus是自由的,因为他们不是任何闭合的Lambda表达式的参数;而x是绑定的,因为它是函数定义的闭合表达式plus x y的参数。

lambda x y . y x :在这个表达式中x和y都是被绑定的,因为它们都是函数定义中的参数。

lambda y . (lambda x . plus x y):在内层演算lambda x . plus x y中,y和plus是自由的,x是绑定的。在完整表达中,x和y是绑定的:x受内层绑定,而y由剩下的演算绑定。plus仍然是自由的。

我们会经常使用free(x)来表示在表达式x中自由的标识符。

一个Lambda演算表达式只有在其所有变量都是绑定的时候才完全合法。但是,当我们脱开上下文,关注于一个复杂表达式的子表达式时,自由变量是允许存在的——这时候搞清楚子表达式中的哪些变量是自由的就显得非常重要了。

参考:http://cgnail.github.io/academic/lambda-1/

http://a.haskellcn.org/topic/4f9e4037edefd68d37010c8b

http://www.cs.yale.edu/homes/hudak/CS201S08/lambda.pdf

http://www.zhihu.com/question/20349066

http://zh.wikipedia.org/zh-cn/%E8%87%AA%E7%94%B1%E5%8F%98%E9%87%8F%E5%92%8C%E7%BA%A6%E6%9D%9F%E5%8F%98%E9%87%8F

http://zh.wikipedia.org/zh-cn/%CE%9B%E6%BC%94%E7%AE%97

时间: 2024-10-04 18:51:16

Lambda演算 Lambda Calculus 的简单理解的相关文章

λ演算 (Lambda Calculus) 一 : 定义与函数式编程

最近在学习计算理论方面的内容,这一系列文章主要介绍λ演算,这需要一些基本的离散数学如集合的知识,写的过程难免有错误欢迎大家指出. 1. 什么是λ演算 (Lambda Calculus)? λ演算是数学家邱奇(Alonzo Church)在20世纪30年代发表的一种计算模型,以变量绑定和替换的规则,每个输入参数用一个字母 λ (lambda)来表示,研究函数如何抽象化定义,函数如何被应用以及递归,最终形成的一套函数化计算规则,被广泛的运用于函数式编程的理论基础. 2. 什么是函数式编程 (Func

lambda演算

先了解下相关的知识点(以下都只用先了解简单的概念,建议wiki): BNF范式,上下文无关文法,函数柯里化. lambda读书笔记演算: http://www.blogjava.net/wxb_nudt/archive/2005/05/15/4311.aspx lambda演算实例 关于lambda演算的定义和解释的确有点让人迷糊,主要不是因为lambda演算有多复杂,而是一些基本概念没有归入正确位置的原因. 这里先写一点草稿,在实践中学习和领悟lambda演算到底是个什么东西. 一:自然数运算

【C++】【lambda】lambda函数介绍和个人理解(3)——lambda的语法甜点

导航: lambda函数介绍和个人理解(1)--初识lambda lambda函数介绍和个人理解(2)--lambda与仿函数 lambda函数介绍和个人理解(3)--lambda的语法甜点 其实,与其说这是一篇介绍lambda语法甜点的文章,不如说是一篇教大家使用lambda函数的一篇文章.当然不可避免的会用到一些有趣的实验.文章略长,大家耐心耐心看吧!当然,这也是本人写的关于lambda函数的最后一篇博文了,如果大家有其他更好的想法或者更深入的理解,请联系我~ 本文大概讲这些内容:基础使用,

lambda演算感想之规则

在lambda演算中,丘奇创建了丘奇数,在理解丘奇数的过程中,逐渐颠覆了一些以前的认知,丘奇数用自己的方式重新定义了数字,即: 0是 lambda s z . z  1是 lambda s z . s z 2是 lambda s z . s (s z) 在理解丘奇数的过程中,我一直在纠结于为何丘奇就可以创建一个数字代表0 1 2,然后还在其中加入了运算规则,因为在我之前的认知中,数字是神圣的,他就像客观事物中的一草一木一样,是不可以被替代的,所以我们不可能在创建一个丘奇数来代替数字,因为数字是唯

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

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演算的关系

莱布尼兹曾经有两个梦想: 1. 创建一种"普遍语言"(universal language)使得任何问题都可以用这种语言表述: 2. 找到一种"判定方法"(decision method)以解决所有可以在"普遍语言"中所表述的问题. 这两个问题是上百年来数理逻辑.数学哲学和数学基础问题的核心.实质.对前一个问题的回答就是自弗雷格.罗素开始,经公理集合论运动的最终结果:以一阶谓词逻辑为语言所形式化阐述的集合论,现在已经成为数学的普遍语言,现代逻辑学

一课掌握Lambda表达式语法及作用简单入门1??

通过三个方面讲解Lambda表达式 1  什么是Lambda表达式 2  Lambda表达式基础知识 3  Lambda表达式高级扩展 分为三个层次去介绍一下Lambda表达式 重构结束后,我们针对性能问题进行讲解, 1 什么是Lambda表达式 2 Model Code As Data 3 功能接口设计及优化 4 为什么要使用Lambda表达式 Lambda表达式,也可以成为箭头函数,匿名函数,闭包 Lambda表达式体现的是轻量级函数方式编程思想 JDK8新特性 -> 左边操作参数,右侧是操

lambda 演算

本文是来自 g9yuayon, 算是一篇读书笔记. :-) 详细内容还是看原作者的. 自由变量 在 (lambda (x) (x y…)) 中, x 是绑定的变量, y 是自由变量 在 (lambda (x) (lambda (y) (x y …))) 中, 要分情况 在第一个 lambda 中, x, y 都是绑定的, 在 第二个 lambda中, x是自由变量 alpha 规则, (转换规则) (lambda (x) (if (= x 0) 1 0)) ;; 等价于 (lambda (y)

数据系统架构——Lambda architecture(Lambda架构)

传统系统的问题 "我们正在从IT时代走向DT时代(数据时代).IT和DT之间,不仅仅是技术的变革,更是思想意识的变革,IT主要是为自我服务,用来更好地自我控制和管理,DT则是激活生产力,让别人活得比你好"--阿里巴巴董事局主席马云. 数据量从M的级别到G的级别到现在T的级.P的级别.数据量的变化数据管理系统(DBMS)和数仓系统(DW)也在悄然的变化着. 传统应用的数据系统架构设计时,应用直接访问数据库系统.当用户访问量增加时,数据库无法支撑日益增长的用户请求的负载时,从而导致数据库服