iBlog@zihua

--

  • 首页
  • 标签
  • 云空间
  • 原创
  • 分类
  • 归档
  • 关于我

  • 搜索
paxos polarfs codebase ask knowledge chatgpt openai 毕业论文 网络安全 共识 分布式 Raft 科研 设计模式 RPC 高并发 多线程 算法设计 碎片技术 Dobbo 吃的 区块链 参考 练习 语言的艺术 SpringCloud 生活 Spring SpringMVC 算法 antic Java MyBatis 书籍细读 JVM 项目教学 SpringBoot Netty

Lambda 演算

发表于 2023-05-23 | 0 | 阅读次数 178

Lambda 演算

Lambda 演算(lambda calculus, λ-calculus), 最初由阿隆佐·邱奇(Alonzo Church)提出, 是世界上最小的编程语言. 尽管没有数字, 字符串, 布尔或者任何非函数的数据类型, lambda 演算仍可以表示任何图灵机.

Lambda 演算由三种元素组成: 变量(variables)、函数(functions)和应用(applications)。

名称 语法 示例 解释
变量 <变量名> x 一个名为"x"的变量
函数 λ<参数>.<函数体> λx.x 一个以"x"(前者)为参数、以"x"(后者)为函数体的函数
应用 <函数><变量或函数> (λx.x)a 以"a"为参数调用函数"λx.x"

最基本的函数为恒等函数: λx.x, 它等价于f(x) = x. 第一个"x"为函数的参数, 第二个为函数体.

自由变量和约束变量:

  • 在函数λx.x中, “x"被称作约束变量因为它同时出现在函数体和函数参数中.
  • 在λx.y中, "y"被称作自由变量因为它没有被预先声明.

求值:

求值操作是通过β-归约(β-Reduction)完成的, 它本质上是词法层面上的替换.

当对表达式(λx.x)a求值时, 我们将函数体中所有出现的"x"替换为"a”.

  • (λx.x)a计算结果为: a
  • (λx.y)a计算结果为: y

你甚至可以创建高阶函数:

  • (λx.(λy.x))a计算结果为: λy.a

尽管 lambda 演算传统上仅支持单个参数的函数, 但我们可以通过一种叫作柯里化(Currying)的技巧创建多个参数的函数.

  • (λx.λy.λz.xyz)等价于f(x, y, z) = ((x y) z)

有时λxy.与λx.λy.可以互换使用.

认识到传统的** lambda 演算没有数字, 字符或者任何非函数的数据类型**很重要.

布尔逻辑:

在 lambda 演算中没有"真"或"假". 甚至没有 1 或 0.

作为替换:

T表示为: λx.λy.x

F表示为: λx.λy.y

首先, 我们可以定义一个"if"函数λbtf, 它当b为真时返回t, b为假时返回f

IF等价于: λb.λt.λf.b t f

通过IF, 我们可以定义基本的布尔逻辑运算符:

a AND b等价于: λab.IF a b F

a OR b等价于: λab.IF a T b

NOT a等价于: λa.IF a F T

注意: IF a b c本质上指: IF((a b) c)

数字:

尽管 lambda 演算中没有数字, 我们还可以用邱奇编码(Church numerals)将数字嵌入到 lambda 演算中.

对于任意数字 n: n = λf.fn 所以:

0 = λf.λx.x

1 = λf.λx.f x

2 = λf.λx.f(f x)

3 = λf.λx.f(f(f x))

要增加一个邱奇数, 我们使用后继函数S(n) = n + 1:

S = λn.λf.λx.f((n f) x)

使用后继函数, 我们可以定义加法:

ADD = λab.(a S)b

挑战: 试定义乘法函数!

变得更小: SKI, SK 和 Iota

SKI 组合子演算
令 S, K, I 为下列函数:

I x = x

K x y = x

S x y z = x z (y z)

我们可以将 lambda 演算中的表达式转换为 SKI 组合子演算中的表达式:

  1. λx.x = I
  2. λx.c = Kc
  3. λx.(y z) = S (λx.y) (λx.z)

以邱奇数 2 为例:

2 = λf.λx.f(f x)

对于里面的部分 λx.f(f x):

  λx.f(f x)
= S (λx.f) (λx.(f x))          (case 3)
= S (K f)  (S (λx.f) (λx.x))   (case 2, 3)
= S (K f)  (S (K f) I)         (case 2, 1)

所以:

 2
= λf.λx.f(f x)
= λf.(S (K f) (S (K f) I))
= λf.((S (K f)) (S (K f) I))
= S (λf.(S (K f))) (λf.(S (K f) I)) (case 3)

对于第一个参数λf.(S (K f))有:

 λf.(S (K f))
= S (λf.S) (λf.(K f))       (case 3)
= S (K S) (S (λf.K) (λf.f)) (case 2, 3)
= S (K S) (S (K K) I)       (case 2, 3)

对于第二个参数λf.(S (K f) I)有:

  λf.(S (K f) I)
= λf.((S (K f)) I)
= S (λf.(S (K f))) (λf.I)             (case 3)
= S (S (λf.S) (λf.(K f))) (K I)       (case 2, 3)
= S (S (K S) (S (λf.K) (λf.f))) (K I) (case 1, 3)
= S (S (K S) (S (K K) I)) (K I)       (case 1, 2)

综上:

  2
= S (λf.(S (K f))) (λf.(S (K f) I))
= S (S (K S) (S (K K) I)) (S (S (K S) (S (K K) I)) (K I))

如果展开这个表达式, 我们最终又会得到邱奇数 2 的相同的表达式.

SK 组合子演算

SKI 组合子演算还可以进一步简化. 我们可以通过I = SKK移除 I 组合子. 我们可以将所有的 I 替换为 SKK.

ι 组合子

SK 组合子仍不是最简的. 定义:

ι = λf.((f S) K)

我们有:

I = ιι
K = ι(ιI) = ι(ι(ιι))
S = ι(K) = ι(ι(ι(ιι)))

引用

  • A Tutorial Introduction to the Lambda Calculus
  • Cornell CS 312 Recitation 26: The Lambda Calculus
  • Wikipedia - Lambda Calculus
  • Wikipedia - SKI combinator calculus
  • Wikipedia - Iota and Jot
  • λ演算 - 维基百科,自由的百科全书
  • SKI组合子演算 - 维基百科,自由的百科全书
@子华 wechat
欢迎友联!
Donate comment here.
@子华 微信支付

微信支付

  • 本文作者: @子华
  • 本文链接: https://liuzihua.top/archives/lambda演算
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
Latency Comparison Numbers
如何基于AskBend复现MySql-Based Knowledge(未写完...)
  • 文章目录
  • 站点概览
@子华

@子华

嗯(⊙_⊙)?

66 日志
6 分类
37 标签
RSS
Creative Commons
Links
  • 爱敲代码的猫
  • ?雨苁ℒ?
  • biezhi(魔王不造反)
  • TyCoding
  • 猿码优创
  • 薛勤的博客
  • 阿里中间件团队博客
  • 沐雨的博客
  • 龙哥的博客
  • Quinn Tian's Blog
  • 方志鹏
  • 在线图片工具
  • jenkov(java很全)
  • 小新の窝
  • 游剑辉
  • Bo Zhou
  • STAR 皆空
0%
© 2018 — 2023 鄂ICP备18029580号-1
主题 - NexT.Muse v5.1.4
as we know, there are known knowns; there are things we know we know. We also know there are known unknowns; that is to say we know there are some things we do not know. But there are also unknown unknowns—the ones we don't know we don't know.