AlgebraticSubtyping

读论文:《Algebraic Subtyping》 -- Dolan

Intro: 代数先于语法(原文 第一章)

类型为什么和代数有关系呢?因为如果引入了子类型这样的特性之后,类型之间就会出现运算,最简单的运算就是判断类型的相等。其次就是引入子类型关系之后,判断类型之间是否兼容(判断子类型关系,一个类型是否是另外一个类型的子类型)。这就相当于抽象代数里面的成员和运算所构成的比如群、环、域之类的东西。通常设计一个语言的时候,可能会优先去找出最简单的描述类型的语法,然后再去尝试基于它构建一个代数类型。比如说我们在引入子类型这个特性的时候。类型通常就会构成一个lattice格。

然而,随着各种各样的类型特性被引入,比如说子类型特性。结构体类型,函数类型。这些类型的复杂交互,甚至可能会导致最终的类型运算在一些复杂的情况不好定义,甚至出现矛盾。在一段时间以内。研究者们可能想了很久,也不知道如何解决这种矛盾。

因此,Dolan提出,首先要找到最简单的兼容这些类型运算的代数系统,然后再基于该类型系统,设计描述类型的语法。(让我想起了物理学里面那种感觉:怎么测光速都不变的时候反过来把光速不变作为基础。)

矛盾的情况 (原文 1.4 Failures of extensibility)

一个最简单的情况是。我们知道通常的类型系统里面有bool类型,函数类型以及结构体类型。但是他们这几个类型之间是不相交的,比如说一个类型不可能同时是布尔类型,又是函数类型。因此这些类型之间是独立的格,而不能够形成一个更大的格。一种非常简单的想法就是引入新的top类型和bottom类型。让它作为这些类型的公共父类型和公共子类型。然而这样形成的整体的格运算发现在实际中会出现严重的问题,甚至无法得出一些非常简单的子类型属性。

最简单的例子就是,如果一个类型同时是函数类型,又同时是结构体类型,那么根据上面的格,他是bottom类型,那么它也是布尔类型的子类型。即可以用作布尔类型。虽然这种情况在常规的编程语言中一开始不存在,但是随后他们可通过比如说C语言的union类型等方式加入了进来。Python这种动态类型的语言也存在这种情况。

为了解决这种情况有几种选择:

  1. coproduct of lattices,比如可以同时维护集合表示可能存在的bool类型,函数类型和结构体类型,如果内部的元素同时有子类型,则说明合并的类型也是子类型。
  2. a coproduct of posets or plain sets。这里简单地加入top和bottom就是直接整个类型集合看作一个元素,弄一个格结构。这样是不对的。

基本概念背景 - 余积(Coproduct):在范畴论中,余积是范畴中的一种泛构造,是积(product)的对偶概念。对于不同的范畴(如集合、偏序集、格),余积的具体实现方式不同。 - 偏序集(Poset):带有偏序关系(自反、反对称、传递)的集合。 - 格(Lattice):一种特殊的偏序集,其中任意两个元素都有唯一的最小上界(并)和最大下界(交)。

Kleene 代数是正则表达式和有限自动机的代数