TAPL《类型和程序设计语言》第一章笔记

1,980 阅读6分钟

第一章:介绍

类型系统(type system)

有观点认为,「类型系统」是一种依据值得类型对语句进行分类,以找出程序缺陷或不良行为的一种行之有效的语法。

A type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute.

这个定义有几点值得商榷的地方。

首先,这个定义说类型系统是针对「编程」而言的,但其实类型系统有更广泛的适用领域,如数学、逻辑学和哲学。不过本书主要讨论编程中的类型系统。

其次,即使是编程中的类型系统,也有两个研究方向:应用方向和理论方向。本书侧重于应用方向,而理论方向可能会研究各种 pure typed lambda calculi 和不同逻辑之间的关联。 比如,实际中很多编程语言不支持递归函数定义,理论研究则肯定会研究一个完备的类型系统。

最后需要补充一点,类型系统可以看作是一种对程序的运行时行为的静态近似计算。因此,有的时候也会算错,明明可以运行,但是还是会报类型错误,比如下面代码:

if <complex test> then 5 else <type error>

如果 <complex test> 总是返回 true,那么 <type error> 就永远不会执行。但类型系统还是会让你把 <type error> 修好。

这是因为类型系统是静态的近似计算,无法算出 <complex test> 的运行时结果。这就导致了类型系统只能找出程序的部分不良行为,比如类型系统会告诉你某个参数必须是数字、某个对象缺少某个属性,但类型系统发现不了被除数为 0、数组越界等问题。

可以由给定语言的类型系统消除的不良行为通常称为运行时类型错误(runtime type errors)。虽然大部分语言的运行时类型错误有很多重叠的地方,但每种语言都有各自想要避免的运行时类型错误,因此每种语言的类型系统的安全性(safety 或 soundness)并不相同。

类型系统的优势

检测错误

类型系统可以在运行代码之前就检测出错误,进而避免更多运行后才会发生的错误。

这使得重构代码变得简单起来,假设一个程序员需要在大型项目中修改一个数据的定义,那么他就不用到处搜索了,因为类型系统会告诉他/她所有类型不一致的地方。

抽象

类型系统的另一个好处是强迫程序员进行更严谨的思考。尤其是在大型项目,模块与组件之间的纽带完全是由类型系统撑起来的,比如模块提供的接口和类。

文档

类型系统能让程序员更快速的阅读代码。

语言的安全性

不幸的是,语言的「安全性」这个概念比「类型系统」更具有争议性,因为每个语言对安全性的理解差异很大。 本书认为「语言的安全性」是指能够对抽象提供保护的语言。每一种高级语言都会对硬件进行抽象,所以本书认为安全性指的是一门语言能确保其抽象的准确性和完备性,也能确保开发者利用这门语言构造出的更高级的抽象的准确性和完备性。

听起来很拗口吧,我们来举个例子。一门语言提供了数组,并提供了读写接口,这其实是对一块连续内存的抽象。 这门语言的使用者认为要改变这个数组,只可能通过这些接口,没有其他办法。再举个例子,如果一门语言支持词法作用域,那么这门语言的使用者就会认为变量能且只能在其词法作用域里使用。

而在一门不安全的语言里,为了理解代码,开发者必须记住所有底层细节,比如数据在内存中的分布情况和顺序。代码的执行结果也会受其运行环境的影响。

语言的「安全性」和「静态类型安全」并不是一回事。语言的安全性可以通过静态类型检查达成,也可以通过运行时检查达成(一遇到非法操作就报错或抛出异常)。比如 Scheme 就是一个安全的语言,但是它并没有静态类型系统。

另一方面,不安全的语言经常会尽力提供静态类型检查器,但根据我们的定义,这样的语言也不能算作是类型安全的。因为这样的语言不能保证 well-typed 程序是 well behaved 的。这些语言的静态检查器能够证明某段代码「有」运行时类型错误,但是不能证明另一段代码「没有」运行时类型错误。

image.png

(这一节后面就不翻译了,有兴趣自己看)

效率

计算机科学史上的第一个类型系统始于 1950 年至 1960 年(如 Fortran 语言),其被引入的目的是为了区分整数运算和小数运算,以提高数学计算效率。因为区分了两种数据后,编译器就可以使用不同的表现形式以生成不同的机器指令和原语操作。现如今的高性能编译器也严重依赖类型检查器在 optimization 阶段和 code-gen 阶段收集到的信息,即使是没有类型系统的语言的编译器也会尽力挖掘类型信息以提高执行效率。

类型系统和语言设计

理想情况下,语言设计应该伴随着类型系统的设计。下文略。

类型简史

最开始的类型系统是为了区别整数和浮点数,后来这种分类法被扩展到结构性数据(如 arrays of records)和高阶函数。70 年代时,一批更为丰富的概念被提出,包括 parametric polymorphism、abstract data types、module systems 和 subtyping,同时,计算机科学家们开始意识到类型系统与数学逻辑的关联,两个领域互相影响直到现在。

image.png

相关阅读资料

  • Handbook articles by Cardelli (1996) and Mitchell (1990b)
  • Barendregt’s article (1992)
  • Foundations for Programming Languages (1996)
  • Reynolds’s Theories of Programming Languages (1998b),
  • The Structure of Typed Programming Languages, by Schmidt (1994),
  • Hindley’s monograph Basic Simple Type Theory (1997)
  • Abadi and Cardelli’s A Theory of Objects (1996)
  • Kim Bruce’s Foundations of ObjectOriented Languages: Types and Semantics (2002)
  • Palsberg and Schwartzbach (1994) and Castagna (1997).
  • Basic Category Theory for Computer Scientists (Pierce, 1991a).
  • Girard, Lafont, and Taylor’s Proofs and Types (1989)
  • Pfenning’s Computation and Deduction (2001).
  • Thompson’s Type Theory and Functional Programming (1991)
  • and Turner’s Constructive Foundations for Functional Languages (1991)
  • Proof Theory and Automated Deduction (1997).

书太多了,我就不翻译了。