Lambda Calculus

Lambda Calculus 在数学定义上面非常简单,并且和与图灵机等价,也就是说FP语言程序与普通的命令式语言如C可以写出同样能力的程序。lambda算子理论里所有东东都是函数.

Lambda 定义

一个 Lambda 定义就是一个:  
    lambda <参数> : <函数体>  
这个定义可以应用到参数上,进行求值。

例(py):

(lambda x : x + x)(5)
10
Currying

在数学定义中 lambda 只有一个参数,我们可以通过 Currying 来实现组合多个参数的能力:

例:

(lambda x : (lambda y : x + y))(1)(2)
3

这里面所包含的思想是“函数本身也是数据,也是值,可以被传递,可以被计算!",在上面的例子中, "第一个函数接受一个参数并返回另一个接受另一个参数的函数",这听起来有些绕,我们分解来看:

lambda x :  接受一个参数x, 这个定义返回如下的值:
       (lambda y: x + y)  这个值是另一个lambda定义,它接受另一个参数y.

我们平常使用的 lambda x, y : x + y 就是上面 currying 这个工具的简单用法.

Closure

终于遇到 Closure 这个词了.closure在我自己的理解就是表示数据的层次性.
closure我曾经见到有本书翻译成"闭包",封闭(closure),或者叫完全有界(complete bounding)。这里的有界和一阶逻辑谓词中的有界是一个意思. 
比如 (lambda x : x + x) , x出现在 lambda x : ....的参数表中, x 就被包含在这个lambda的  context 里面. 再比如前面 currying 的那个例子:
(lambda x : (lambda y : x + y))  y 出现在内层的 lambda 中,它的 context就是内部的那个lambda.  而没有出现在 lambda .. 这里的变量就是自由变量.在这里内部的  lambda y : x + y 中, x 是一个自由变量, y 是有界变量. 在整个  lambda x : ... 的定义中,x,y 都是有界变量.

例:

y = 2
(lambda x : x + y)(4)
6

y 没有出现在 lambda 的参数表中,这里它绑定的是外部context中的 y, 是一个自由变量.

另一个例子:

a = 1
(lambda a : a + 1)(2)
3

这里, lambda 中的a 与外界的a 不同,因为context不同.

当一个 lambda表达式的所有变量都有界时,此表达式才完全合法.

从这个意义上讲,整个运行环境可以看作是一个大的 lambda表达式, 所有的函数以及变量,肯定要定义在某一个层次上.

lambda算子计算规则: alpha, beta

alpha 转换

就是说lambda表达式中的参数名称可以随意替换, 名字本身不重要.通过alpha转换可以实现递归等操作.

例:
lambda x, y : x + y

lambda a, b : a + b 完全等价.

beta简化

Beta规则无非是说,应用一个函数(也就是lambda表达式。一个意思)等价于通过把函数体内有界的变量替换成应用里对应参数的实际值来替换原来的函数。

例: (lambda x, x + 2) (1) 相当于把 1 替换掉x, 于是得到: 1 + 2

另一个例子:

f = (lambda y : (lambda x : x + y))(5)
f(2)
7
f(1)
6
这里应用一个函数生成了一个 add5 的函数, 动态语言的强大哦, :D
上面的例子,相当于生成了: lambda x : x + 5 这样一个表达式.

再看一个例子:

(lambda x, y : x(y))(lambda x : x * x, 3)
9

这个例子中, lambda x, y 将x 应用到 y 上. 其中 x 替换成 lambda x : x * x , y 替换成 3.
Beta的严格定义如下:

lambda x . B e = B[x := e] if free(e) /subset free(B[x := e]

这条规则是为了保证出现命名冲突的时候,先进行 alpha 替换,然后再应用 beta 简化.

至此, 通过 lambda , currying, closure, alpha, beta 已经定义出一个"完备"的计算体系. 在此之上,我们可以继续构造出更复杂的程序.

丘奇数对数字的定义

FP里面只有函数,没有其他^ ^ 数字其实也是函数.
丘齐数里,所有的数字都是两个参数的函数:

零是 lambda s z . z
一是 lambda s z . s z
二是 lambda s z . s (s z)
任意数n,就是将 s 应用到 z 上n次.
这里可以把 z 看作 zero, s 看作 succeed 函数.

Church 数把数字看作是函数的应用, 一个数字n 就是"数"5下. 至于它的理论价值,据说很牛,我也不大了解,略了.

现在,有了基本函数概念与变换规则,以及数的概念,还缺少"分支选择" , "重复操作(递归)”
选择结构

Boolean值的定义

boolean值同样是通过函数定义生成的:

T = lambda x, y : x
F = lambda x, y : y

逻辑操作的定义, 这个定义实在是太美妙了~ 不得不令人感叹数学之美,世间复杂万物都可以由简单的概念演绎生成。 

逻辑与:

BoolAnd = lambda x, y : x(y, F)
BoolAnd(T, F)
<function <lambda> at 0x00CD0A30>
F
<function <lambda> at 0x00CD0A30>

BoolAnd 的两个参数是 T 或 F,当然,他们都是函数,返回的结果也是一个函数。 上面的例子中, T && F 返回结果为 F (是一个函数,这个函数的地址与 F 相同,因此确认为F)。或者用下面的方式来检验:

T == BoolAnd(T, T)
True
F == BoolAnd(T, F)
True
F == BoolAnd(F, T)
True
F == BoolAnd(F, F)
True

逻辑或:

BoolOr = lambda x, y : x(T, y)
BoolOr(T, F)
T == BoolOr(T, F)
f(2)
7
>>> f(1)
6
这里应用一个函数生成了一个 add5 的函数, 动态语言的强大哦, :D
上面的例子,相当于生成了: lambda x : x + 5 这样一个表达式.

再看一个例子:

>>> (lambda x, y : x(y))(lambda x : x * x, 3)
9
>>>

这个例子中, lambda x, y 将x 应用到 y 上. 其中 x 替换成 lambda x : x * x , y 替换成 3.
Beta的严格定义如下:

lambda x . B e = B[x := e] if free(e) /subset free(B[x := e]

这条规则是为了保证出现命名冲突的时候,先进行 alpha 替换,然后再应用 beta 简化.

至此, 通过 lambda , currying, closure, alpha, beta 已经定义出一个"完备"的计算体系. 在此之上,我们可以继续构造出更复杂的程序.

丘奇数对数字的定义


FP里面只有函数,没有其他^ ^ 数字其实也是函数.
丘齐数里,所有的数字都是两个参数的函数:

零是 lambda s z . z
一是 lambda s z . s z
二是 lambda s z . s (s z)
任意数n,就是将 s 应用到 z 上n次.
这里可以把 z 看作 zero, s 看作 succeed 函数.

Church 数把数字看作是函数的应用, 一个数字n 就是"数"5下. 至于它的理论价值,据说很牛,我也不大了解,略了.


现在,有了基本函数概念与变换规则,以及数的概念,还缺少"分支选择" , "重复操作(递归)”
选择结构

Boolean值的定义


boolean值同样是通过函数定义生成的:
>>> T = lambda x, y : x
>>> F = lambda x, y : y

逻辑操作的定义, 这个定义实在是太美妙了~ 不得不令人感叹数学之美,世间复杂万物都可以由简单的概念演绎生成。
逻辑与:

>>> BoolAnd = lambda x, y : x(y, F)
>>> BoolAnd(T, F)
<function <lambda> at 0x00CD0A30>
>>> F
<function <lambda> at 0x00CD0A30>
>>>
BoolAnd 的两个参数是 T 或 F,当然,他们都是函数,返回的结果也是一个函数。 上面的例子中, T && F 返回结果为 F (是一个函数,这个函数的地址与 F 相同,因此确认为F)。或者用下面的方式来检验:
>>> T == BoolAnd(T, T)
True
>>> F == BoolAnd(T, F)
True
>>> F == BoolAnd(F, T)
True
>>> F == BoolAnd(F, F)
True
>>>
逻辑或:

>>> BoolOr = lambda x, y : x(T, y)
>>> BoolOr(T, F)
>>> T == BoolOr(T, F)
True
F == BoolOr(F, F)
True
T == BoolOr(T, T)
True
T == BoolOr(F, T)
True

逻辑非:

BoolNot = lambda x : x(F, T)
F == BoolNot(T)
True
T == BoolNot(F)
True

If-Then-Else

基本分支程序,程序结构同样是函数定义-_-!

IfThenElse = lambda cont, T_expr, F_expr: cont(T_expr, F_expr)

IfThenElse(T, 1, 2)
1
(一个问题, 我们定义的 T, F 如何与 Python 原生的 true, false 通用呢? 比如,如何写: IfThenElse(3>2, 1, 2) 这样的? )

用一个比较 dirty 的方法来解决这个问题:

def BOOL(b):
if b: return T
else: return F

IfThenElse(BOOL(3>2), 1, 2)
1

(ok, 我所参考的中文blog翻译就到此为止了,实在等不下去了,自己啃英文原文去了 - 9/12/06)
http://goodmath.blogspot.com/2006/06/lamda-calculus-index.html

Why oh why Y?

前面从底向上构造了数字,bool,选择结构,现在还缺少能够重复执行的机制。在lambda演算中实现重复的方式是“递归”,但是 lambda表达式没有名字,只有函数,于是用 Y combinator 的技巧。Y combinator 是 lambda 表达式的不动点操作符~ 

(It's called the Y combinator, aka the lambda fixed point operator)

简单的递归的例子,当然是我最爱的 Factorial 的定义:
形式定义:
factorial(n) = 1 if n = 0
factorial(n) = n*factorial(n-1) if n > 0

<erlang>:
factorial(0) -> 1;
factorial(N) -> N * factorial(N-1).

<python>:
def factorial(N):
if N == 0:
return 1
else:
return N * factorial(N-1)

Y combinator 是一个高阶函数,它的定义如下:

let Y = lambda y . (lambda x . y (x x)) (lambda x . y (x x))

<py>

Y = lambda y:(lambda x : y(x(x)))(lambda x:y(x(x)))

……看上去好复杂啊。原文有一个树型的 lambda 图,可以很好的解释为什么这个操作叫做 Y ,因为看上去这个表达式就是一棵倒置的树。
这个表达式的特别之处是: 将其应用于本身会得到本身…… (好绕)
(Y Y) = Y (Y Y)
我把python的那个执行了: Y(Y) 结果是死循环,这个结果看来是不对的?

Y(Y)

Traceback (most recent call last):
File "<pyshell#68>", line 1, in -toplevel-
Y(Y)
File "<pyshell#67>", line 1, in <lambda>
Y = lambda y:(lambda x : y(x(x)))(lambda x:y(x(x)))
File "<pyshell#67>", line 1, in <lambda>
Y = lambda y:(lambda x : y(x(x)))(lambda x:y(x(x)))

把 Y 进行一系列的展开,alpha,beta转换,最终 (Y Y) = Y (Y Y)
That's the magic of Y: it reproduces itself. (Y Y) = Y (Y Y) = Y (Y (Y Y)), forever. Y combinator 的作用就是生成了自身,然后自身再生成自身,直到永远~~ 这就是上面的程序死循环的原因.顺便想到,这个 Y 定义的形式非常像 Lisp 中打印自身的那个程序, 这也可能就是为什么很多人热衷于编写打印自身的程序的一个深层次背景.

等等!! 忽然有点灵光!我们是需要重复执行的能力,现在我们得到了一个死循环的结果, 我们可以重复的执行一些东西了~!

通过Y组和可以实现递归,至于具体的细节,这里做个记号,继续研究.

Lazy evaluation

(lambda x y . x * y) 3 ((lambda z. z * z) 4)

对于这样的组合表达式,有两种展看的方式:

(1) 3 * ((lambda z. z*z) 4)

(2) (lambda x y. x*y) 3 (4 * 4)

两种方式结果一样,但是有时候会有区别.第一种方式称为 lazy evalutiaon, 延迟求值, 第二种方式称为eager evaluation。 高阶函数与延迟求值是 FP的两个强有力的工具。

在实际语言中 Lisp, Scheme, ML使用 eager evaluation, Haskell,Miranda使用 Lazy evaluation。

Combinatiors

combinator 是组合器,前面介绍了Y combinator, 下面再说几个:

S = lambda x, y, z: x(z)(y(z))
K = lambda x: lambda y: x
I = lambda x:x
S: S is a function application combinator;



……看上去好复杂啊。原文有一个树型的 lambda 图,可以很好的解释为什么这个操作叫做 Y ,因为看上去这个表达式就是一棵倒置的树。
这个表达式的特别之处是: 将其应用于本身会得到本身…… (好绕)
(Y Y) = Y (Y Y)
我把python的那个执行了: Y(Y) 结果是死循环,这个结果看来是不对的?

>>> Y(Y)

Traceback (most recent call last):
File "<pyshell#68>", line 1, in -toplevel-
Y(Y)
File "<pyshell#67>", line 1, in <lambda>
Y = lambda y:(lambda x : y(x(x)))(lambda x:y(x(x)))
File "<pyshell#67>", line 1, in <lambda>
Y = lambda y:(lambda x : y(x(x)))(lambda x:y(x(x)))

把 Y 进行一系列的展开,alpha,beta转换,最终 (Y Y) = Y (Y Y)
That's the magic of Y: it reproduces itself. (Y Y) = Y (Y Y) = Y (Y (Y Y)), forever. Y combinator 的作用就是生成了自身,然后自身再生成自身,直到永远~~ 这就是上面的程序死循环的原因.顺便想到,这个 Y 定义的形式非常像 Lisp 中打印自身的那个程序, 这也可能就是为什么很多人热衷于编写打印自身的程序的一个深层次背景.

等等!! 忽然有点灵光!我们是需要重复执行的能力,现在我们得到了一个死循环的结果, 我们可以重复的执行一些东西了~!

通过Y组和可以实现递归,至于具体的细节,这里做个记号,继续研究.

Lazy evaluation

(lambda x y . x * y) 3 ((lambda z. z * z) 4)

对于这样的组合表达式,有两种展看的方式:

(1) 3 * ((lambda z. zz) 4)

(2) (lambda x y. x
y) 3 (4 * 4)

两种方式结果一样,但是有时候会有区别.第一种方式称为 lazy evalutiaon, 延迟求值, 第二种方式称为eager evaluation。 高阶函数与延迟求值是 FP的两个强有力的工具。

在实际语言中 Lisp, Scheme, ML使用 eager evaluation, Haskell,Miranda使用 Lazy evaluation。

Combinatiors

combinator 是组合器,前面介绍了Y combinator, 下面再说几个:
>>> S = lambda x, y, z: x(z)(y(z))
>>> K = lambda x: lambda y: x
>>> I = lambda x:x
S: S is a function application combinator;
K: K generates functions that return a specific constant value
I: I is the identity function

一个使用例子:

S(K, K, 1)
1
S(K,K,"hello")
'hello'

S(K,K, x) 这个组合,实际上就是 I 所完成的功能,也就是说通过 S K 来组合便实现了 I的一个等价物。据说,我们可以通过S K两个 combinator便实现所有 lambda 算子的等价物!! 太不可思议了。

作者:lu_ming
来源:CSDN
原文:https://blog.csdn.net/Lu_ming/article/details/1427635
版权声明:本文为博主原创文章,转载请附上博文链接!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,010评论 0 2
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,071评论 0 2
  • sì 支zhī茶chá 对duì 酒jiǔ,赋fù 对duì 诗shī,燕yàn子zi 对duì 莺yīng 儿é...
    每个人的孟母堂阅读 1,073评论 0 6
  • 一年级语文上册生字表 生字表一(共400字) 啊(ā)爱(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang阅读 2,628评论 0 6
  • (开经偈) 无上甚深微妙法 百千万劫难遭遇 我今见闻得受持 愿解如来真实义 第一品 Fǎ huì yīn yóu ...
    黄一轩阅读 2,364评论 0 1