Lambda演算

一个前人写的有关Lambda演算的项目,里面包含了一个完整的关于Lambda演算的起源和讲解的pdf文件,还有能在不同平台下运行的解释器。

Lambda演算是一套用于研究函数定义、函数应用和递归的形式系统。它由 Alonzo Church 和 Stephen Cole Kleene 在 20 世纪三十年代引入,Church 运用 lambda 演算在 1936 年给出 判定性问题 (Entscheidungsproblem) 的一个否定的答案。这种演算可以用来清晰地定义什么是一个可计算函数。关于两个 lambda 演算表达式是否等价的命题无法通过一个通用的算法来解决,这是不可判定性能够证明的头一个问题,甚至还在停机问题之先。

这篇文章写于软工与计算一刚刚上完Lambda演算之后,因为理论和应用之间存在很大的距离,很多人觉得Lambda演算没有什么作用,这篇文章注在以更简单直白的语言为大家讲解Lambda演算并且告诉大家这个东西究竟有什么用。


首先先讲一讲Lambda演算里面得几个定义和几个操作:

定义

定义1. 项

假设我们有一个无穷的字符串集合,里面的元素被称为变量(和程序语言中变量概念
不同,这里就是指字符串本身)。那么 项定义如下:

  1. 所有的变量都是 项(名为原子)
  2. 若 和 是 项,那么 ( ) 也是 项(名为应用)
  3. 若 是 项而 是一个变量,那么 (.) 也是 项(名为抽象)。

解释

1.函数包括因变量和自变量,自变量作为变量可以看成 项,因变量本质上也是一个变量(废话),所以因变量也是变量,可以简单的认为几乎所有的东西都是 项
2.简单来说,就是可以将括号内部的东西看成一个整体。
3.即一种函数的表达方式,表示这是一个函数,是函数里的一个变量,是表达式
(下面为了方便起见,所有的都用\代替,这也是解释器中的写法)

这些都是项

(.( ))
((.(.)))
(((( ) ) ) )
(((.(.( ))) ) )
((.) (.( )))
(.( ))

在lambda演算里面,括号是非常重要的(在一般的数学里也很重要),它涉及到了运算的顺序和后面β规约的时候能不能正确规约
下面介绍三个括号省略的规则:
1.最外层的括号可以省略,(\x.x)可以写成\x.x
2.左结合的应用型的lambda项,如(((MN)P)Q),括号可以省略,表示为M N P Q(这个规则十分重要)
3.抽象型的lambda项,(.)的M里最外层的括号可以省略,如\x.(xy)可以写成\x.xy

省略表示
..
(.. )
.(. ( )) . ( )
.. .
完整的lambda项
(.(.((( ) ) )))
(((.(.( ))) ) )
(.((.( ( ))) (.( ( )))))
(.(.(( ) (.))))

在后面演算的时候,将括号复原是非常重要的事情

定义2:语法全等

我们用恒等号来表示两个lambda项完全相同,即他们具有完全相同的结构,对应位置上的变量也完全相同,就像矩阵全等一样

定义3:自由变量

对一个 项 ,我们可以定义 中自由变量的集合 FV() 如下:

  1. FV() = {}
  2. FV(.) = FV() \ {}
  3. FV( ) = FV() ∪ FV( )

从第 2 可以看出抽象 . 中的变量 是要从 中被排除出自由变量这个集合的。若 中有,我们可以说它是被约束的。据此可以进一步定义约束变量集合。值得注意的是,对同一个 项来说,这两个集合的交集未必为空。

几个简单的例子:
项 的 自由变量集合 FV()
.. 的自由变量集合 {, }
的自由变量集合{, , , }
.. 的自由变量集合{, }
(注意,在第四个例子中,\y.\x.x中被约束的变量确实是x y,但是这和开头的x y不同,因为\y.\x.x同样可以写成\a.\b.b,这就像f(x)可以写成f(a)一样,抽象中的只是一个符号而已,但是符号的重复会给计算带来很大的困难,建议还是使用不同的。另一方面,如果对于lambda项P来说,FV(P) = ∅,则称 P 是 封闭的,这样的 P 又称为组合子。)

定义4:出现

对于 项 和 ,可以定义一个二元关系出现。我们说 出现在 中,是这样定义的:

  1. 出现在 中;
  2. 若 出现在 中或 中,则 出现在 ( ) 中;
  3. 若 出现在 中或 ≡ ,则 出现在 (.) 中。

定义5:替换

对任意 , , ,定义 [/] 是把 中出现的自由变量 替换成 后得到的结果,这个替换有可能改变部分约束变量名称以避免冲突。

其实在原文本中给出了7个非常抽象的例子,在这里笔者用简单的语言来描述一下这里发生了什么事情

对于\f.\x. f (\f.\x.x) f x这个lambda项来说,有些人会把f或者(f x)当成一个lambda项替换开头的\f.\x,这是不可以的(但可以替换它前一个括号里的抽象),因为在这个lambda项的真实表达式(即补满了括号)中,f x均是约束变量,不能替换自己,另一方面,lambda项中的变量都是假变量,即都是无意义的符号变量,就像定积分中的



一样,你把x换成t或者别的不影响任何事情。

说到底,lambda演算还是一种解释性的语言,它并不要求计算出任何具体的数值,而是去解释这个函数/抽象,并且可以随意替换。

定义 6: 变换和 等价

设 . 出现在一个 项 中,且设 ∉ FV(),那么把 . 替换成.[/]
的操作被称为 的 变换。当且仅当若 经过有限步(包括零步) 变换后,得到新的 项 ,则我们可以称 与 是 等价的。

这个就是上面说的假变量

定义 7: 规约

形如(.) 的 项被称为 可约式,对应的项[/] 则称为 缩减项。当 中含有 (.) 时,我们可以把 中的 (.) 整体替换成 [/] ,用 指称替换后的得到的项,那么我们说 被 缩减为 ,当 经过有限步(包括零步)的 缩减后得到 ,则称 被 规约到

这个就是刚刚说的替换的事情

到这里,整个lambda演算的体系已经基本建立起来了,只需要再定义一些ZERO,ADD,POW,TRUE,FALSE等的lambda项即可,也即程序设计语言。

ZERO = \f.\x.x
SUCC =\n.\f.\x.f(n f x)
PLUS = \m.\n.m SUCC n
MULT = \m.\n.\f.m(n f)
POW = \b.\e.e b
PRED = \n.\f.\x.n(\g.\h.h(g f))(\u.x)(\u.u)
SUB = \m.\n.n PRED m

一个简单的例子

SUCC ZERO
• \n.\f.\x.f (n f x) \f.\x.x
• \f.\x.f (\f.\x.x) f x
• \f.\x.f x

TREU = \x.\y.x
FALSe = \x.\y.y
AND = \p.\q.p q p
OR = \p.\q.p p q
NOT = \p.\a.\b.p b a
IF = \p.\a.\b.p a b
ISZERO = \n.n(\x.FALSE)TRUE
LEQ = \m.\n.ISZERO(SUB m n)[如果GEQ将m n 交换了位置]
EQ = \m.\n. AND(LEQ m n)(LEQ n m)

到这里,Lambda里面的基本定义和易错易混的地方笔者已经全部解释清楚了。接下来还有一个叫不动点的概念,主要是用来处理递归/迭代的Lambda表达式的双重应用。
Y = \g.(\x.g (x x))\x.g(x x)
YF = (\g.(\x.g (x x))\x.g(x x)) F
= (\x.F (x x))\x.F(x x)
= F(\x.F(x x))(\x.F(x x))
= F(YF)
最后把软工一的十道题放上来,供大家练习和参考。
1.I = \x.x
S = \x.\y.\z.x z(y z)
I =S I = \x.\y.\z.x z(y z) \x.x
=\y.\z. (\x.x)z(y z)
=\y.\z. z(y z)
I m n = \y.\z.z(y z) m n
= n (m n)

2.ZERO = \f.\x.x
SUCC = \n.\f.\x.f(n f x)
SUCC(SUCC ZERO)=SUCC(\n.\f.\x.f(n f x) \f.\x.x)
=SUCC(\f.\x.f(\f.\x.x)f x)
=SUCC(\f.\x.f x)
=\n.\f.\x.f(n f x) (\f.\x.f x)
=\f.\x.f (\f.\x.f x)f x
=\f.\x.f f x

3.POW = \b.\e.e b(TWO = \f.\x.f f x THREE = \f.\x.f f f x)
POW TWO THREE=\b.\e.e b TWO THREE
=THREE TWO
=\f.\x. f(f(f(x))) TWO
=\x. TWO(TWO(TWO(x)))
=\x. TWO(TWO(\a.\b. a(a(b)) (x))
=\x. TWO(TWO \b. x(x(b))
=\x. TWO((\c.\d. c(c(d))(\b. x(x(b)) ))
=\x. TWO(\d. (\b. x(x(b)) ( \b. x(x(b)) d ) ) )
=\x. TWO(\d. (\b. x(x(b)) ( \b. x(x(b)) d ) ) )
=\x. TWO(\d. (\b. x(x(b)) ( x(x(d)) ) ) )
=\x. TWO(\d. (x(x(x(x(d))))) )
=\x. \e.\f. e(e(f)) (\d. (x(x(x(x(d))))) )
=\x. \f. (\d. (x(x(x(x(d))))) ) ( ( \d. (x(x(x(x(d))))) ) f))
=\x. \f. (\d. (x(x(x(x(d))))) ) (x(x(x(x(f)))))
=\x. \f. (x(x(x(x(x(x(x(x(f)))))))))
=\f. \x. (f(f(f(f(f(f(f(f(x)))))))))

  1. NOT(NOT TRUE)=(\p.\a.\b.p b a)((\p.\a.\b.p b a)(\x.\y.x))
    =(\p.\a.\b.p b a)((\a.\b.(\x.\y.x) b a))
    =(\p.\a.\b.p b a)(\a.\b.b)
    =(\a.\b.(\a.\b.b) b a)
    =(\a.\b.a)= TRUE
    IF(OR FALSE FALSE)a b=IF((\p.\q.p p q)(\x.\y.y)(\x.\y.y))a b
    =(\p.\a.\b.p a b)((\p.\q.p p q)(\x.\y.y)(\x.\y.y))a b
    =(\p.\a.\b.p a b)((\x.\y.y)(\x.\y.y)(\x.\y.y))a b
    =(\p.\a.\b.p a b)(\x.\y.y)a b
    =\x.\y.y a b
    =b

  2. LEQ=\m.\n.ISZERO(SUB m n)
    GEQ =NOT LEQ
    =(\p.\a.\b.p b a) LEQ
    =\a.\b (\m.\n ISZERO(SUB m n)) b a
    =\a.\b(ISZERO(SUB b a))

  3. FACT1 =\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))
    FACT = FACT1 FACT1
    FACT THREE = FACT1 FACT1 THREE
    =\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) \f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) THREE
    =IF(ISZERO THREE)ONE(MULT THREE (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) \f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (PRED THREE)))
    =(MULT THREE (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) \f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (PRED THREE)))
    =(MULT THREE (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) \f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) TWO))
    =(MULT THREE (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) \f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) TWO))
    =(MULT THREE (IF(ISZERO TWO)ONE(MULT TWO ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (PRED TWO))))
    =(MULT THREE TWO ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (PRED TWO))))
    =(MULT THREE TWO ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))ONE)))
    =(MULT THREE TWO ((IF(ISZERO ONE)ONE(MULT ONE ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))ONE) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))))(PRED ONE))) ))
    =(MULT THREE TWO (MULT ONE ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))ONE) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))))(PRED ONE))) ))
    =(MULT THREE TWO (MULT ONE ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))ONE) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n))))ZERO))))
    =(MULT THREE TWO (MULT ONE ((IF(ISZERO ZERO)ONE(MULT ZERO ((\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))) (\f.\n.IF(ISZERO n)ONE(MULT n (f f (PRED n)))) (PRED n)))ONE) ))))
    =(MULT THREE TWO (MULT ONE ONE))
    =\f.\x f f f f f f x

7.ADD = W(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))
ADD TWO FOUR = W(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) TWO FOUR
= \x.x (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) TWO FOUR
= (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) TWO FOUR
=(IF(ISZERO FOUR)TWO((\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(SUCC TWO)(PRED FOUR)))
=IF(ISZERO FOUR)TWO((\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(THREE)(THREE))
=(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) THREE THREE
=IF(ISZERO THREE)THREE((\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(SUCC THREE)(PRED THREE))
=(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))FOUR TWO
=IF(ISZERO TWO)FOUR((\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(SUCC FOUR)(PRED TWO))
=(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))FIVE ONE
=IF(ISZERO ONE)FIVE((\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(SUCC FIVE)(PRED ONE))
=(\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))SIX ZERO
=IF(ISZERO ZERO)SIX((\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m))) (\f.\n.\m.IF(ISZERO m)n(f f(SUCC n)(PRED m)))(SUCC SIX)(PRED ZERO))
=SIX = \f.\x f f f f f f x

8.FACT2 =\f.\n. IF(ISZERO n)ONE(MULT n(f (PRED n)))
FACTY = Y FACT2
FACTY THREE = Y FACT2 THREE
=FACT2(Y FACT2) THREE
=\f.\n. IF(ISZERO n)ONE(MULT n(f (PRED n)))(Y FACT2)THREE
=IF(ISZERO THREE)ONE(MULT THREE (Y FACT2 (PRED THREE)))
=IF(ISZERO THREE)ONE(MULT THREE (FACT2(Y FACT2)(TWO)))
=MULT THREE (FACT2(Y FACT2) TWO)
=MULT THREE (IF(ISZERO TWO)ONE(MULT TWO (Y FACT2 (PRED TWO))))
=MULT THREE (MULT TWO (Y FACT2 (ONE)))
=MULT THREE (MULT TWO (MULT ONE (Y FACT2 ZERO)))
=MULT THREE (MULT TWO (MULT ONE ONE))
=MULT THREE (MULT TWO ONE)
=MULT THREE TWO
=\f.\x. f f f f f f x

  1. CAR = \p.p TRUE
    CDR =\p.p FALSE
    TRUE = \x.\y.x
    FALSE =\x.\y.y
    CAR(CDR(CONS a(CONS b(CONS c NIL))))=\p.p TRUE (\t.t FALSE(CONS a(CONS b(CONS c NIL))))
    =\p.p TRUE(\t.t (\x.\y.y)(CONS a(CONS b(CONS c NIL))))
    =\p.p TRUE(\x.\y.y CONS a(CONS b(CONS c NIL)))
    =\p.p TRUE(CONS b(CONS c NIL))
    =\x.\y.x (CONS b (CONS c NIL))
    = b

  2. LENGTH NIL =LENGTH \x.TRUE
    =Y (\g.\c.\x. NULL x c (g (SUCC c) (CDR x))) ZERO NIL
    =Y F ZERO \x.TRUE
    =(\g.\c.\x. NULL x c (g (SUCC c) (CDR x)))(Y F )ZERO NIL
    =NULL NIL ZERO (Y F(SUCC ZERO)(CDR NIL))
    =(\p.p(\x.\y.FALSE)) NIL ZERO(Y F(SUCC ZERO)(CDR NIL))
    =(\x.TRUE(\x.\y.FALSE))ZERO(Y F(SUCC ZERO)(CDR NIL))
    =\x.\y.x ZERO (Y F(SUCC ZERO)(CDR NIL))
    =ZERO

你可能感兴趣的:(Lambda演算)