码迷,mamicode.com
首页 > 其他好文 > 详细

Lambda演算 Lambda Calculus 的简单理解

时间:2015-04-19 09:01:19      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:

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 

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



Lambda演算 Lambda Calculus 的简单理解

标签:

原文地址:http://my.oschina.net/xinxingegeya/blog/403472

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!