λ演算
在B站看到了有人讲解λ演算 很感兴趣 于是去了解了一下
原视频:https://www.youtube.com/watch?v=RcVA8Nj6HEo&t=44s
原视频很精彩 图文描述 我也是看了这个视频写的 推荐观看
什么是λ演算
λ演算(Lambda Calculus)是一种用于研究函数定义、函数应用和递归的数学逻辑系统 由阿隆佐·丘奇(Alonzo Church)在 1930 年代提出。它是计算理论的基础之一 并在编程语言的设计中发挥了重要作用 特别是对函数式编程语言(如 Haskell、Lisp 和 ML)有深远的影响
诶 这里学过python的人肯定想到了 python中有个lambda表达式 是不是和这个λ演算相关呢
没错 Python 中的 lambda 表达式确实与 λ(Lambda)演算有关系 但它只是 λ演算的一个简单应用 并没有完全实现 λ演算的全部概念 这里不过多叙述 只是告诉大家他们之间确实有关系
λ演算的基本概念
λ演算由三种基本表达式组成:
- 变量:例如 x、y,代表某个值。
- λ抽象(Lambda Abstraction):用于定义匿名函数,例如 λx.x+1 表示“输入 x,返回 x+1”
- 函数应用(Function Application):用于调用函数,例如 (λx.x+1) 2,表示将 2 代入 λx.x+1,结果为 3
λ表达式
在λ演算中 主要有三类样式:
- 括号:()
- 变量:x, y, z…
- “λ”和”.”:λ和.总是成对出现
这样 我们就有了三个模版:
- (_ _)
- a
- (λa._)
这里的下划线可以填入上述任意模块 a是一个变量 我们可以像搭积木一样进行构造
例如:
((λa.y)(λx.(λc.e)))
并且 这些变量也可以是一个函数
结合代码理解
上述的a其实就是一个变量 并且他也可以看成一个函数
现在我们重点看看( _ _ ) 和 ( λa._ )
(_ _)可以理解为
1 | #以(ab)为例 |
(λa._)可以理解为
1 | #以(λx.y)为例 |
这些就是λ表达式的内容
λ图
有很多种可视化λ图
- Tromp图表:https://tromp.github.io/cl/diagrams.html
- David C Keenan的λ演算图形符号:https://dkeenan.com/Lambda/
- de Bruijn索引:https://en.wikipedia.org/wiki/De_Bruijn_index
- Vex(Wayne Citrin,Richard Hall,Benjamin Zorn):https://www.researchgate.net/publication/2726047_Programming_with_Visual_Expressions
- 视觉λ演算(Viktor Massalõgin):https://github.com/bntre/visual-lambda
λ演算的计算规则
λ演算主要有三个计算规则:
- α-变换(Alpha Conversion)
- β-规约(Beta Reduction)
- η-变换(Eta Conversion)
α-变换(Alpha Conversion)
简单来说就是变量重命名
λx.x = λy.y
只要不影响表达式的意义 就可以更改变量名称 就像你可以随意地取变量名
β-规约
函数应用的计算
我们来看这样的一个式子:
((λx.x+2)3)
根据前文的理解
我们逐步进行分析
首先来看内层的(λx.x+2)
这个意思相当于是 我们定义个一个函数叫x 函数的返回值是x + 2
1 | #(λx.x+2) |
接下来我们看外层 还记得前面说的
引用
以(ab)为例
将左边的a看成一个函数
右边的b就是这个函数a的输入
现在把刚才的(λx.x+2)看成a 把3看成b
于是 ((λx.x+2)3)就可以用python写成
1 | def x(x): |
其用数学符号就是
3 + 2
综上 ((λx.x+2)3)等价于 3 + 2
η-变换
函数等价转换
先给出定义
λx.fx 等价于 f
只要 f 在所有输入 x 上都保持不变 那么 λx. f x 和 f 是等价的
什么意思呢
以f(x) = x + 3为例
假设有f(x) = x + 3
在 λ 形式下 他可以表示为
f = λx. x + 1
那么 λx.fx 等价于 f 即
λx. (λx. x + 1) x ≡ λx. x + 1
自由变量与束缚变量
定义
束缚变量(Bound Variable)
如果一个变量 x 出现在 λx.M 这样的函数定义中 并且 x 是由 λx 绑定的 则 x 是束缚变量
简单理解:变量被 λ 绑定 就称为束缚变量自由变量(Free Variable)
如果一个变量 x 在 λ 表达式中出现 但没有被任何 λ 绑定 则 x 是自由变量
简单理解:变量没有被 λ 绑定 它就是自由变量
自由变量
1 | λx. y // 变量 y 是自由变量 |
束缚变量
1 | λx. x // 变量 x 是束缚变量 |
组合子
在λ演算中,组合子(Combinator) 是指 没有自由变量 的 λ 表达式 也就是说 组合子是 只包含束缚变量 的 λ 表达式 它们是纯粹的函数抽象 不依赖于外部环境 因此它们可以被认为是“自给自足”的函数
组合子 之所以叫这个名字 是因为它们不依赖外部的变量或环境 只能依赖自己定义的参数 并且可以通过组合多个组合子来构建复杂的计算 组合子本质上是 λ 演算中的基础构建模块 类似于函数式编程中的高阶函数
恒等组合子
恒等组合子就是一个接受一个参数并返回这个参数的组合子 它的定义非常简单:
1 | I = λx. x |
作用:恒等组合子返回输入参数本身 不做任何改变
I 5 → 5
K 组合子
K 组合子(又叫 K 函数或常量函数)接受两个参数 但只返回第一个参数 它的定义是:
1 | K = λx. λy. x |
作用:返回第一个参数 忽略第二个参数
K 5 10 → 5
在这个例子中 K 5 返回的是一个函数 λy. 5 再与任何第二个参数(比如 10)结合时 结果依然是 5
S 组合子
S 组合子(又叫 S 函数)比较复杂 接受三个参数 并执行一些组合操作 它的定义如下:
1 | S = λx. λy. λz. (x z) (y z) |
作用:S 组合子将输入的两个函数 x 和 y 应用于相同的参数 z 并将结果作为两个函数的输出
S (λx. x + 1) (λx. x * 2) 3 → (λx. x + 1) 3 (λx. x * 2) 3
→ 3 + 1 3 * 2
→ 4 6
S 组合子可以用于组合多个函数,使得它们的输入可以共享。
组合子的性质
组合子通常具有一些有用的性质 它们可以与其他组合子进行组合 以实现更加复杂的计算 几个重要的性质包括:
函数应用
组合子是纯粹的 λ 演算表达式 它们的行为仅依赖于传入的参数 可以通过函数应用来将它们的计算结果传递给其他组合子 进一步构建复杂的计算无外部依赖
组合子是完全自足的 它们的定义仅依赖于它们自己内部的参数 不需要从外部环境引入其他变量 这使得它们在编程语言和计算机科学中非常重要 尤其是在函数式编程中高阶函数
组合子本质上是高阶函数(Higher-Order Function)它们可以作为输入传递给其他函数 或者返回作为结果 例如,S 组合子通过两个输入函数生成新的函数 具有高度的抽象能力
λ演算的作用
说了这么多 大家应该会进行一些关于λ演算的计算了 可λ演算有什么用呢 感觉就是换个抽象的形式进行计算
其实λ演算本质上是换了一种抽象的方式来进行计算 但它的意义远不止于此
计算理论的基础
λ演算与图灵机(Turing Machine)一样 是计算理论的两大核心模型之一 它们都能表达可计算函数 但λ演算采用的是纯粹的函数变换 而图灵机基于状态和存储
- 通过 λ演算 可以定义所有可计算的函数 因此它是图灵完备的
- 计算机科学家用它来研究可计算性、算法复杂度等问题
影响现代编程语言
λ演算是函数式编程的理论基础 影响了 Haskell、Lisp、ML、Scala、JavaScript(匿名函数、箭头函数)、Python(Lambda 表达式)等编程语言 例如
- 匿名函数(Lambda 表达式)
1 | add = lambda x, y: x + y |
- 高阶函数(函数可以作为参数传递)
1 | def apply_func(f, x): |
现代语言的 闭包(Closure)、惰性求值、纯函数 等概念都源于 λ演算
形式化数学 & 逻辑推理
λ演算被用作数学逻辑的基础,特别是在构造主义数学和类型理论中。例如:
- Curry-Howard 对应:λ演算中的函数和逻辑推理中的证明之间存在对应关系 程序可以被视为数学证明
- 依赖类型(Dependent Types):Coq、Agda 这些数学证明工具都基于λ演算的扩展形式
递归与无变量编程
λ演算能够表示 递归,即使它本身没有显式的循环结构。例如,阶乘可以用 Y 组合子(Y Combinator)来实现:
1 | factorial = \f. \n. if n == 0 then 1 else n * (f (n - 1)) |
编译器优化
λ演算提供了转换和简化代码的规则 例如:
- β-规约(函数应用) 可以减少计算步骤 优化执行效率
- α-变换(变量重命名) 可避免变量名冲突
- η-变换(函数简化) 可以减少不必要的函数包装 提高性能
许多编译器(如 GHC Haskell、Scala、Lisp 解释器)都会用 λ演算作为中间表示(IR)帮助优化代码
并发 & 分布式计算
λ演算的无状态特性使其非常适用于并发计算和分布式系统 例如:
- MapReduce(Google 的大规模数据处理模型)依赖于 λ演算的映射与归约思想
- Actor Model(Erlang、Akka)与函数式编程紧密相关 受λ演算启发
- Title: λ演算
- Author: 姜智浩
- Created at : 2025-04-01 11:45:14
- Updated at : 2025-04-01 09:27:02
- Link: https://super-213.github.io/zhihaojiang.github.io/2025/04/01/20250401λ演算/
- License: This work is licensed under CC BY-NC-SA 4.0.