这本小书来源于1986至1987年秋季学期于Université Paris VII开设的一门关于类型演算的短期研究生课程. 它并不意图是百科全书式的, 例如Church-Rosser定理就没有证明, 而且主题的选取是相当随意的.
关于逻辑的基本常识是必要的, 然而我们也并不会陷入乏味的细节之中.
理论计算尚非科学. 许多基本概念亟待澄清, 并且当前该领域的研究遵循一种"婚礼蛋糕"范式: 例如, 语言设计让人想到Ptolemy天文学——不断需要更加深入的修正. 然而, 也存在一些有限的主题, 例如复杂度理论和指称语义学, 它们相当远离这种批判.
在这样的情况下, 方法论式的评论极其重要, 因为我们不得不将方法论视为战略而将具体的结果视为具有战术性质.
我们尤其感兴趣的东西可在1900年代的逻辑漩涡的源头找到, 由Frege, Löwenheim, Gödel等名字刻画. 不熟悉逻辑学史的读者应该参考[4].
让我们从一个例子开始. 存在一个乘法的标准过程, 它由输入和产生结果. 对于这个事实我们可以言称什么?
最初的尝试是言称我们拥有了一个等式这个等式在数学主流中以言称两边指称相同的整数且是Cantor的图的意义下的一个函数而获得了含义. (译注: 这里"整数"的原文是"integer", 又有原注, 全文的integer将表示natural number: )
这是指称性的方面, 无疑是正确的, 然而它忽略了基本的点.
存在一个有限的计算过程表明这两个指称是相等的. 言称等于是一种滥用 (这并非什么廉价的哲学——而是一个具体的问题), 因为如果我们所拥有的这两个东西真是相同的, 那么我们就不会感到陈述它们的相等性的需要了. 具体地说, 我们在问一个问题, , 然后得到了一个答案, . 这两个表达式具有不同的涵义, 而我们必须做些什么 (编制证明或者进行计算, 或是至少查询百科全书) 来表明这两个涵义具有相同的指称.
关于, 将其称为一个(作为图的)函数是不正确的, 因为加载了乘法程序的机器无法容纳下一个无限的图. (译注: 这句话是说实无限是不可能容纳于一个经典计算机器之中的, 当然潜无限的确是可以的.) 因此, 我们不得不总结道, 我们面对的是与这个涵义之问相关的一种有限的动力学.
尽管指称在很早的阶段就被建模, 涵义则被推向了主观主义, 导致当前的数学对于涵义的处理或多或少沦为了句法操作. 这在我们所要讨论的主题的本质之下并非先验, 而我们可以期待在接下来的几十年里找到一种对于计算的处理, 它结合了指称语义学 (数学的清晰性) 和句法 (有限的动力学) 的优点. 本书显然坐落于传统之上, 这种传统基于不幸的当前状况: 在无限的静态的指称与有限的动态的涵义的对立之中, 指称性的一方要远比另一方先进.
于是乎, 逻辑中由Frege指出的最根本的一个区分是: 给定一个句子, 存在两种看待它的方式:
拥有相同涵义的两个句子当然拥有相同的指称, 这是显然的; 但是两个拥有相同指称的句子很少拥有相同的涵义. 例如, 取一个复杂的数学等价. 两个句子拥有相同的指称 (它们同时为真), 但肯定拥有不同的涵义; 不然的话, 表明这种等价的意义何在?
这个例子允许我们引入一些成组的想法:
这个传统 (早在Frege的时代之前就由Boole开始) 基于对Ockham剃刀的激进应用: 我们相当轻易地舍弃了涵义, 只考虑指称. 澄清这种对于逻辑的肢解的合理性的是其可操作的一面: it works!
建立了这种传统的主导性地位的基本转折点在于1916年的Löwenheim定理. 如今, 人们可以将模型论视为这种业已古老的认识论选择所带来的丰富回报. 实际上, 从指称的角度, 即从操作的结果的角度来看, 如此考虑逻辑, 我们发现了一种有些特殊的代数, 但它允许我们去检视对于更加传统的代数而言并不熟悉的操作. 实际上, 避免局限于等式性变体而考虑一般的可定义结构也是可以的. 因此, 模型论常以fruitful的方式为代数的想法和方法注入了活力.
另一方面, 全然忘记指称而专注于涵义
是不可能的, 这出于简单的原因, 即涵义包含指称, 至少是隐式地包含. 因此, 这并非对称的情况. 实际上, 几乎不存在统一的句法观点, 因为我们从未能够赋予神秘的涵义以一种操作性的涵义. 关于涵义唯一可感知的现实在于其被写下来的方式, 即形式化; 但是, 形式化仍然是一种不够理想的研究对象, 不具备真切的结构, 就像一片soft camembert.
这难道意味着纯粹句法的方法毫无讨论的价值吗? 当然不是, 1934年Gentzen的著名定理表明在句法层面上逻辑具有某些深远的对称性 (由切消表达). 然而, 这些对称被句法的不完美之处掩盖了. 换句话说, 它们不是句法的对称, 而是涵义的对称. 但是, 要想更进一步, 我们必须要将那些对称表达为句法的性质, 而结果并不是很美丽.
那么, 总结我们对于这种传统的观点, 它总是在寻找其根本概念, 也就是说, 涵义和句法之间的操作性区别. 或者把话说得更具体些, 它意在寻找深刻的句法的几何形状上的不变量: 其中可以找到涵义.
被称为句法性
(因为没有更加高贵的名字了) 的传统, 从没能达到其对手的高度. 近些年来, 也就是说代数传统繁荣发展的时期, 句法传统不值一提, 并且无疑可能将因为缺少问题和方法论而在一二十年内消失. 这个灾难因为计算机科学 (伟大的句法操纵装置) 得以避免, 其提出了一些非常重要的理论问题.
其中一些问题 (例如关于算法复杂度的) 似乎更多地需要逻辑的字面而非逻辑的灵魂. 另一方面, 一切和程序的正确性和模块性有关的问题都深刻诉诸于句法传统, 诉诸于证明论. 我们被引导至从可追溯到1930年的Herbrand的根本性定理开始对于证明论进行修订. 这个修订给那些一度被认为永远固定下来了的领域带来了新的光亮, 那里曾在很长一段时间内盛行着墨守成规.
在句法逻辑传统与计算机科学之间的交流中, 人们可以在计算的一侧等待着新的语言和新的机器. 但是, 在逻辑的一侧 (也就是本书的主要作者所在的领域), 人们终于可以期望用上一直被残忍忽视的概念基础了.
这种传统以极端的陈词滥调为人所知: 联结词被翻译为或
, 诸如此类. 这种解释没有告诉我们关于逻辑联结词的特别突出的东西: 它显然的抱负缺乏是其可操作性的潜在理由. 我们只关心句法的句子 (封闭表达式) 的指称, 或.
正如我们之前所言, 句法性的观点展现了逻辑学的某种深远的对称. Gentzen的相继式演算以特别令人满意的方式完成了这种观点. 不幸的是, 其计算上的意义在某种程度上被其句法上的复杂性所掩盖, 尽管这种复杂与本质无关, 但是从来没有真正被克服. 这就是为什么我们在处理相继式演算之前要先呈现Prawitz的自然演绎.
自然演绎在某种意义上是有点悖论性的系统. 其局限于直觉主义的情形 (在古典情形下没有什么良好的性质), 但是它也只是对于语言的部分令人满意而已: 我们将对于和的考虑推迟到第10章. 尽管如此, 析取和存在是两种最典型的直觉主义的联结词!
自然演绎的基本想法是一种不对称: 一个证明大致上是一个树状的结构, 其有一个或多个假设 (也可能没有), 但是只有一个结论. 这种演算的深刻对称在于相互精准匹配的引入和消去规则. 我们应该顺便观察到这样的事实, 对于这样一种树状结构, 我们总是可以唯一地确定哪一条规则是最后被使用的. 如果有多个结论的话, 那是无法做到的.
我们将使用记号来指对于的一个演绎(deduction), 即停止于. 这个演绎会被写成一个有限的树的形式, 并且树的叶子会被标记以句子. [译注: 这个指的不是带标签的树 (labelled tree).] 对于这些句子, 存在两种可能的状态, 死或生. [译注: 更准确地说, 是对于这些叶子.]
在通常状态下, 一个句子是活着的, 也就是说其在证明中还处于活跃的地位: 我们称其是一个假设(hypothesis). 典型的情况由自然演绎的第一条规则刻画, 其允许我们构造一个仅包含一个句子的演绎:这里的既是叶子也是根; 从逻辑上说, 我们推出了, 但这只是因为是被假定成立的!
现在位于叶子位置的句子是可以死去的, 当其不再于证明中活跃时. 死去的句子可以通过杀死活着的句子得到. 最典型的例子是的引入规则:以上的演绎必须按照如下方式理解: 我们从的一个演绎开始, 在这个的演绎中, 我们选取了特定数目的的出现作为假设 (这个数字可以是任意的: ), 然后我们构造了一个新的演绎, 其结论是, 但是其中的这些选定的的出现都会被discharged, 即被杀死. 可能还存在其他的出现我们选择不去discharge.
这条规则很好地刻画了树状的记号的样貌: 知道何时一个假设被discharged是重要的, 因而有必要记录这种信息. 但是如果在以上的例子中这样做, 这意味着我们需要将被叉掉的和规则那行连起来; 但是连起来之后这个东西就不再是之前我们所考虑的真正的树结构了!
一些注记:
所有的规则, 除了, 都保持the stock of hypotheses: 例如, 以上以作结的演绎, 其假设是两个立即子演绎的假设.
出于众所周知的逻辑原因, 有必要将限制于变量不能在任何假设中自由出现的情形 (但是, 从另一方面说, 其可以在死去的叶子中自由出现).
这个系统的基础对称在于引入/消去对称, 其代替了不能在这种上下文中被实现的假设/结论对称.
原注: 变量属于对象语言 (其可能代表一个数字, 一个数据记录, 一个事件). 我们为演算的变量保留符号, 下一节我们将引入这个概念. [译注: 元语言和对象语言是相对的概念.]
我们将以Heyting语义的角度重新检视自然演绎系统. 我们固定原子公式的解释以及量词的范围. 一个公式将被看成是其所有可能的演绎构成的集合; 不说"证明了", 我们说"".
然后自然演绎的规则就以构造函数的特别方式显现: 以为假设的一个演绎, 可以被看成是一个函数, 其联系以结果. 实际上, 为了使得这种对应精确, 我们需要处理parcels of hypotheses: 相同的公式可能在假设中出现多次, 而在相同的parcel中的两次的出现应该对应于相同的变量.
以上的内容听起来似乎有些神秘, 但是通过一些例子, 其很快就会变得清晰起来.
我们已经看到Heyting的想法在自然演绎的框架之下执行得非常好. 我们将建立一个类型化项 (typed term) 的形式系统以讨论藏在证明背后的泛函对象. 这个系统的意义是藉由我们已经写下的泛函方程给出的. 实际上, 这些方程可以用两种不同的方式阅读, 这再次强化了涵义和指称之间的二分:
当然, 第二种观点和第一种比起来有欠发展, 至少对于逻辑学是这样! 例如, 程序的指称语义 (例如, Scott语义) 有很多: 对于这种语义, 程序的执行过程中没有东西会发生变化. 另一方面, 几乎没有任何打磨精致的程序的操作语义 (我们排除只是粗糙重述迈向规范形式的步骤的ad hoc语义). 建立真正的算法的操作语义或许是计算机科学中最重要的问题.
类型和命题之间的对应在[3]之中建立起来.
当我们以Heyting的精神思考证明, 公式就成为了类型. 具体来说, 类型如下:
这与命题演算的相对应: 原子命题写作, 成为, 成为.
证明就成了项. 更准确地说, 的一个证明 (作为公式) 成为一个具有类型的项 (作为类型). 具体来说, 项如下:
类型代表了某种正在被讨论的对象. 例如, 一个具有类型的对象是一个从到的函数, 一个具有类型的对象是一个序对, 由一个的对象和一个的对象构成. 原子类型的含义是不重要的, 其依赖于上下文.
一般来说, 项代表程序. 程序的目的在于计算其指称, 或者至少是将指称置于一种便利的形式. 程序的类型被视为一种描述(specification), 即程序(抽象地)做了什么. 先验地说这是一种具有形式"这个程序计算两个整数之和"的评论.
一个项被称为规范的, 如果没有其子项具有形式:
本章关心的是确保类型化演算能够在计算上表现良好的两个结果. 规范化定理提供了规范形式的存在性, 而与此同时Church-Rosser性质保证了其唯一性. 实际上, 对于后者而言, 我们仅是简单陈述其内容但不加以证明, 因为其确非类型论的内容, 而且在许多文献中都有很好的讲解了, 例如[1].
规范化定理具有两种形式:
这个性质表达了规范形式的唯一性, 这独立于其存在性. 实际上, 它对于其他演算来说也有意义, 例如无类型演算, 在无类型的演算里规范化定理不成立.
Church-Rosser定理
这个结果陈述了每个项的规范形式的存在性, 当然它必然也是唯一的. 其立即的推论在于指称相等的可判定性.
归功于Gentzen, 相继式演算是对于逻辑学的对称的最漂亮刻画. 其与自然演绎有着诸多类似之处, 但是不局限于直觉主义的情形.
这种演算一般来说被计算机科学家所忽略, 尽管其刻画了某些基础性的想法: 例如, Prolog这种语言是对于相继式演算的部分实现, 而自动定理证明领域使用的"tableaux"方法不过是这种演算的一个特殊情形. 换言之, 它浑然不觉地被许多人使用, 但是混杂了控制特性, 即编程设备 (programming device). 使得这一切运作的是相继式演算及其深刻的对称性, 而不是什么特别的技巧. 所以说, 若是不知道相继式演算的微妙之处, 是很难考虑, 例如, Prolog的理论的.
从算法的角度来说, 相继式演算没有Curry-Howard同构, 这是因为太多书写相同证明的方式. 这阻止了我们将其当作类型化演算使用, 尽管我们瞥见了某种类似物的深层结构, 可能与并行有关. 但是, 它需要对于句法的新方法, 例如带有多个结论的自然演绎.
一个相继式是一个表达式, 其中和是公式的有限序列和.
幼稚的(指称性)解释在于的合取推出了的析取, 特别地
这些规则, 似乎什么也没说, 强制规定了管理"槽"的一种特定方式, 在槽中人们书写公式. 规则如下, 它们是:
事实上, 与流行的认知相反, 这些规则才是整个演算里最重要的部分. 这是因为, 在还没有写下任何一个逻辑符号之前, 我们实际上就已经能够确定逻辑操作的未来行为. 尽管这些规则从指称的角度来看是显然的, 但是我们应该从操作的角度仔细检视这些规则, 特别是收缩.
传统上人们认为逻辑是一种形式游戏, 一连串或多或少有些随意的公理和规则. 相继式演算 (当然自然演绎也是) 表明实际上完全不是这么一回事: 人们可以自娱自乐地发明他们自己的逻辑操作, 但是这些逻辑操作不得不尊重左/右对称, 否则的话他们发明的就只是一种毫无趣味的逻辑暴行. 具体来说, 对称指的是我们可以消除切规则.
本章我们将证明简单类型演算的强规范化定理, 但是既然
第3章中我们允许额外的常量类型; 现在我们将描述两种这样的类型, 分别是 (整数) 和 (布尔).
译注: 根据第1章的原注, 本书的整数都是指自然数.
除了常见的五种, 对于和存在特定的scheme. 我们保持了使用引入/消去术语, 因为这些scheme还将出现在之后的之中.
译注: 在某种意义上这里有点符号滥用.
除了经典的redex, 我们加入了:
在中, 所有的规约序列都是有限的, 并将导向相同的规范形式.
典型的例子是逻辑联结词:例如, 和. 但是, 从另一方面来说, 如果遇到了表达式, 那么我们就不知道该做什么了.
问题. 有没有一种可能定义另外一种析取, 但它是对称的?
在第9.3.1小节的时候, 我们将看到, 根据语义方法, 可以说明不存在具有类型的项满足
首先我们必须表示整数: 选择用来表示整数是显然的.
经典的函数可以用简单的递推关系定义 [虽然译者觉得应该说是递归?]. 让我们给出加法的例子: 我们需要从我们已经熟知的定义方程开始:
考虑:这表明我们可以将当作的一个定义.
通过类似这种风格的简单练习, 我们可以自娱自乐地定义乘法, 幂, 前继, 等等.
整数上的谓词当然也可以被定义, 例如给出了这允许我们将一个特征函数 (类型) 转换为一个谓词 (类型).
这些例子都没有严肃地运用高阶类型. 然而, 随着在递归中使用的类型的增加, 越来越多的函数变得可以表达. 例如, 如果具有类型, 我们可以定义类型为的为那么就是了. 作为具有类型的对象, 函数是:
很容易看出来, 通过某个合理的函数的有限迭代, 我们可以超越每个原始递归函数. 例如, 给定返回的函数 (Ackermann函数) 就要比所有原始递归函数增长得更快.
译注: 上面这段话不是很理解, 因为我不知道什么是.
这种函数在中很容易定义, 只要我们使用一个复杂类型上的递归, 例如: 取, 其对于将被规范化为, 对于将被规范化为.
为了给本小节作结, 我们应该指出中的的第二个参数实际上经常是不用的. 可能有人更倾向于使用迭代子而不是, 其应用于具有类型的, 具有类型的, 以及具有类型的, 而规则是:
满足等式
指称语义学领域最早的工作是由[Scott69]对于无类型演算完成的, 自那时起已经又有很多内容了. 他的方法由连续性刻画, 即保持有向join. [译注: 有很多人将join翻译成并, 但是我感觉这不是很好.] 本章介绍了一种新型的domain论 [译注: 有人将domain论翻译成论域论, 我觉得也容易造成误解], 其中我们也有上有界的meet (拉回), 并且meet也得到保持. 这种性质, 被称为稳定性, 最初是由[Berry]引入的, 其试图给出顺序算法的语义刻画. 我们将发现这种语义很适合系统, 并且它会将我们引向线性逻辑.
指称语义的基本想法在于解释规约 (一种动态概念) 以相等性 (一种静态概念). 换言之, 我们对于演算的不变量进行建模. 这是在说, 存在着模型和模型: 自Gödel (1930) 起, 如何将模型构造为极大一致扩张就已经是众所周知的了. 这当然不是我要说的东西, 因为这种方法没有给出信息.
我们心中已经有毋须用纸笔写下的幼稚解释, 即类型的一个对象是一个从到的函数, 现在让我们来看看能否赋予词汇函数
以一个合理的含义. 以这种方式, 我们尽力去避免贪大求全, 而是去寻找简单的几何想法.
第一个想到的会是以下内容:
Kreisel有着以下的想法 (hereditarily effective operation):
Scott的想法就好多了:
原注1. 这个问题最常见的回答 (但是完全不意味着是放之四海而皆准的回答) 是使用紧开拓扑. 在这种拓扑里, 函数位于一个基本的开集中, 如果该函数限制于某个预先刻画的紧集时, 其值位于某个预先刻画的开集里. 这种拓扑只在空间是局部紧 (每个点都有紧邻域基) 时表现良好, 即便如此函数空间也不必自身是局部紧的.
为了解决这些问题, Scott