简单易懂的程序语言入门小册子(1.5):基于文本替换的解释器,递归定义与lambda演算的一些额外说明
这一篇接在第一篇lambda演算的后面。讲讲一些数学知识。
经常有些看似很容易理解的东西,一旦要描述得准确无误,就会变得极为麻烦。 软件工程里也有类似情况:20%的代码实现了核心功能,剩下80%的代码处理边界情况。 于是,所谓的准确描述里的大部分文字都在说明边界情况,核心概念只有寥寥几字——好比一件打满补丁的衣服,完全看不出原来的样子。 出现这种现象要么是人类的大脑有缺陷,难以严谨而又准确的理解概念,也就是说人类太笨; 要么就是语言系统有问题,难以简洁地表达概念,而发明不出新的语言系统的人类还是很笨。 无怪乎“人类一思考,上帝就发笑”。 这一节打算尽量严谨地描述λ演算里的一些符号的含义,希望不会写得太繁琐。
递归定义
实数的链表List一般定义为: List=nil|⟨R,List⟩
这个文法实际上是定义了一个集合List,我用集合运算的符号重写List的定义: List={nil}∪{⟨r,l⟩|r∈R,l∈List}
比如说,我现在想知道List是什么。 这时我脑里有List这个符号,但是我还不知道List代表什么内容。 然后我就来看这个定义,结果看到定义里的第二行用到了List,但是我这时候还没不知道什么是List呢!
所以,为了具体解释递归定义到底定义了什么,我下面用一种构造性的方法来定义List。
首先,基础情况是空链表nil,构造一个只包含nil的集合,记为List0。 List0={nil}
在Listi的定义中让i趋向无穷看看会怎样? 由于当i趋向无穷时有Listi=Listi−1=List,所以我们得到了List的递归定义。
下面用同样的思路描述了λ演算的语法: M0=XMi=X∪{λx.m|x∈X,m∈Mi−1}∪{(mn)|m∈Mi−1,n∈Mi−1}M=limi→∞Mi
归约派生的等价关系
数学让人如此讨厌大概是因为它严谨得像处女座一样。 在我们计算λ演算的表达式时,我们这样写: ((λy.λx.(xy)a)λz.z)=(λx.(xa)λz.z)=(λz.za)=a
归约(α归约、β归约和η归约)实质上是一个集合,这个集合的元素是二元组⟨m,n⟩。 这个二元组的意思是m可以归约到n。 这里混合这三种归约的关系记为符号→。 “混合”是并集的意思。 →定义为: →=→α∪→β∪→η
→是不是=呢? 如果是的话我就不会特地选用其他符号了。 我们知道,一个等价关系=是一个满足以下三种特性的关系:
- 自反性:m=m,也就是自己等于自己;
- 对称性:如果m=n,那么n=m;
- 传递性:如果m=n并且n=l,那么m=l。
用这三个特性扩展→。扩展后的关系记为≈: m≈mm→n⇒m≈nm≈n⇒n≈mm≈n,n≈l⇒m≈l
≈还不是我们需要的等号=! 看下面例子: ((λy.λx.(xy)a)_λz.z)≈(λx.(xa)_λz.z)错!(λy.λx.(xy)a)≈λx.(xa)对!
所以,还要在≈的基础上添加最后一个特性,添加后就是=了: m≈m′⇒m=m′m=m′⇒λx.m=λx.m′m=m′⇒(mn)=(m′n)n=n′⇒(mn)=(mn′)
终于讲完=是什么意思了。 但是还有一个“小问题”。 =的计算过程并非唯一的。 比如下面这个例子: (λx.x(λy.ya)_)=(λx.xa)_=a(λx.x(λy.ya))_=(λy.ya)_=a
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人