类型系统综述(二)

原书作者:Luca Cardelli,Microsoft Research
本文整理:Koshiba

译者注释使用下划线标注,方便识别。

接续上一篇于国庆期间发布的类型系统综述,本文将简要介绍有类型 λ \lambda λ 演算 的类型系统,以及如何在此基础上扩充 U n i t Unit Unit 类型(单一, 并不知道如何翻译,感觉单一类型比单位类型好听;且毕竟不可能是单子类型——单子这个词一般留给了 monad。), B o o l Bool Bool 类型(布尔), N a t Nat Nat 类型(自然数), P r o d u c t Product Product 类型(积), U n i o n Union Union 类型(联合), R e c o r d Record Record 类型(记录), V a r i a n t Variant Variant 类型(变体)。

本文涵盖了 Type Systems by Luca Cardelli 1 的第三章(一阶类型系统)的大部分内容。因第三章的内容,特别是 公式 较多,我们将余下的 Reference 类型(引用),Recursive 类型(递归)以及数组和列表留给下次。全文没有使用 \mathit{},留给渲染器,看造化了。

一阶类型系统和有类型 λ \lambda λ- 演算

在大多数常见的过程式语言中发现的类型系统都是一阶的。从类型理论特有的术语来看,它囊括了(令人困惑的)高阶函数,但缺乏类型参数化和类型抽象——而这是二阶(类型系统)的特征。历史上的 Pascal 和 Algol 68 有丰富的一阶类型系统,而 Fortran 和 Algol 60 的类型系统就比较差了。

我们可以给无类型的 λ λ λ- 演算一个最小的一阶类型系统。其中无类型的 λ λ λ 抽象 λ x . M λx.M λx.M 表示参数为 x x x 、返回 M M M 的函数。类型化该演算系统 只需要函数类型和一些基本类型;我们将在后面看到如何增加其他常见的类型结构。

一阶类型化的 λ λ λ- 演算被称为系统 F1。 与无类型的 λ λ λ- 演算相比,主要的变化是为 λ λ λ- 抽象(即函数定义)增加了类型标注,它的语法是 λ x : A . M λx:A. M λx:A.M,其中 x x x 是函数参数, A A A 是参数的类型,而 M M M 是函数体。(在一个类型化的编程语言中,我们可能会标注函数体的类型,但在这里没有必要。)从 λ x . M λx. M λx.M λ x : A . M λx:A.M λx:A.M 是任何从无类型语言到类型化语言的典型 < u>(但不是必须):约束变量具有类型标注。

由于 F1 主要基于函数,其中最有趣的类型也是函数类型。 A → B A \to B AB 是具有 A A A 型参数和 B B B 型结果的函数类型。我们还需要一些基本类型来建立函数类型,我们用 B a s i c Basic Basic 表示这种基本类型的集合,用 K ∈ B a s i c K \in Basic KBasic 表示任意一种基本类型。(就目前来说,设立基本类型纯粹是技术上的需要,但不久我们将考虑有趣的基本类型,如 B o o l Bool Bool N a t Nat Nat。)

下面给出了 F1 的语法。对类型化语言中的语法进行简单的描述是很重要的。在无类型的 λ λ λ- 演算的情况下,上下文无关文法(context-free grammars)描述了所有合法的程序。但在类型化的 λ λ λ- 演算中却不是这样,因为良好的行为(通常)不具备 “上下文无关” 这一美好的性质——描述合法程序的任务由类型系统来承担。例如, λ x : K . x ( y ) λx:K.x(y) λx:K.x(y) 尊重下面给出的语法,却也不是 F1 的程序,因为它不是类型良好的——这里 K K K 不是一个函数类型 < u>(但具有 K K K 类型的 x x x 却被当做函数使用)。为了定义自由变量和约束变量的概念以及语言的作用域规则,上下文无关文法依然是必要的。基于作用域规则,那些只在约束变量上有差异的项,如 λ x : K . x λx:K.x λx:K.x λ y : K . y λy:K.y λy:K.y,在语法上是相同的。这种方便的识别在类型规则中是隐含的 < u>(且为了应用某些类型规则,我们可能必须重新命名约束变量)。

A , B : : = 类型   K K ∈ B a s i c 基本类型 ∣   A → B   函数类型 \begin{aligned} A, B ::=& \qquad &\text{类型} \\ &\ K \quad K \in Basic \qquad &\text{基本类型} \\ \mid &\ A \to B \qquad &\text{函数类型} \end{aligned} A,B::= KKBasic AB 类型基本类型函数类型

M , N : : =   项   x 变量 ∣   λ x : A .   M 函数, λ  抽象 ∣   M   N 函数应用,函数调用 \begin{aligned} M, N ::=&\ \qquad &\text{项} \\ & \ x \qquad &\text{变量}\\ \mid &\ \lambda x:A.\, M \qquad &\text{函数,$\lambda$ 抽象}\\ \mid &\ M\ N \qquad &\text{函数应用,函数调用} \end{aligned} M,N::=  x λx:A.M M N变量函数,λ 抽象函数应用,函数调用

(F1 的自由变量的定义与无类型的 λ λ λ- 演算基本相同,只需额外地将类型标注忽略即可。)

F1 只需要三个简单的断言,见下表。断言 Γ ⊢ A \Gamma \vdash A ΓA 在某种意义上是多余的,因为所有语法正确的类型 A A A 在任何环境 Γ \Gamma Γ 中都是良好的。(然而,在二阶系统中,类型是否良好并不能仅仅通过语法来体现,因此判断 Γ ⊢ A \Gamma \vdash A ΓA 变得至关重要。)但我们现在还是包括了这个断言,这样以后的扩展会比较容易。
Γ ⊢ ⋄ 环境  Γ  是定义良好的 Γ ⊢ A 类型  A  在环境  Γ  下是定义良好的 Γ ⊢ M : A M  是在环境  Γ  下具有类型  A  的定义良好的项 \begin{aligned} & \Gamma \vdash \diamond \qquad & \text{环境 $\Gamma$ 是定义良好的} \\ & \Gamma \vdash A \qquad & \text{类型 $A$ 在环境 $\Gamma$ 下是定义良好的} \\ & \Gamma \vdash M : A \qquad & \text{$M$ 是在环境 $\Gamma$ 下具有类型 $A$ 的定义良好的项} \end{aligned} ΓΓAΓM:A环境 Γ 是定义良好的类型 A 在环境 Γ 下是定义良好的M 是在环境 Γ 下具有类型 A 的定义良好的项
这些断言的有效性由下表中的规则给出。

  • 规则(Env)是唯一一个不需要假设的规则(即,它是 唯一的公理)。它指出,空环境是一个有效的环境。

  • 规则(Env x)用于将环境 Γ \Gamma Γ 扩展到一个更大的环境 Γ , x : A \Gamma, x:A Γ,x:A,条件是 A A A Γ Γ Γ 中的一个有效类型。请注意,当我们假设 Γ ⊢ A \Gamma \vdash A ΓA 成立时也意味着 Γ Γ Γ 必须是定义良好的(根据归纳法)。也就是说,在推导 Γ ⊢ A Γ \vdash A ΓA 的过程中,我们必须先推导出 Γ \Gamma Γ 。这个规则(即 Env x)的另一个要求是,变量 x x x 不得在 Γ \Gamma Γ 中定义。

  • 我们要注意保持变量在环境中的独立性,所以当 Γ , x : A ⊢ M : B \Gamma, x:A \vdash M : B Γ,x:AM:B 被推导出时,如(Val Fun)的假设,我们知道 x x x 不能出现在 d o m ( Γ ) dom(\Gamma) dom(Γ) 中。(如果 x x x 已经在 d o m ( Γ ) dom(\Gamma) dom(Γ) 中出现,则我们可以通过对 λ λ λ- 抽象(即函数)的形参 x x x 重命名来避免冲突并使得规则可以应用,如上文所述。)

  • 规则(Type Const)和(Type Arrow)构造定义良好的类型。

  • 规则(Val x)从环境中提取了一个假设并使用它。我们使用符号 Γ ′ , x : A , Γ ′ ′ Γ', x:A, Γ'' Γ,x:A,Γ 来非正式地表示 x : A x:A x:A 出现在环境的某个地方。

  • 规则(Val Fun)将类型 A → B A \to B AB 赋予某个函数,条件是函数体在形式参数具有类型 A A A 的假设下有类型 B B B

  • 规则(Val Appl)将一个函数应用于一个参数:在验证条件时,相同的类型 A A A 必须出现两次。

ϕ ⊢ ⋄ ( Env  ϕ ) \frac{}{\phi \vdash \diamond} (\text{Env}\ \phi) ϕ(Env ϕ)

Γ ⊢ A x ∉ d o m ( Γ ) Γ , x : A ⊢ ⋄ ( Env  x ) \frac{\Gamma \vdash A \qquad x \notin dom(\Gamma)}{\Gamma, x:A \vdash \diamond}(\text{Env}\ x) Γ,x:AΓAx/dom(Γ)(Env x)

Γ ⊢ ⋄ K ∈ B a s i c Γ ⊢ K ( Type Const ) \frac{\Gamma \vdash \diamond \qquad K \in Basic}{\Gamma \vdash K}(\text{Type Const}) ΓKΓKBasic(Type Const)

Γ ⊢ A Γ ⊢ B Γ ⊢ A → B ( Type Arrow ) \frac{\Gamma \vdash A \qquad \Gamma \vdash B}{\Gamma \vdash A \to B}(\text{Type Arrow}) ΓABΓAΓB(Type Arrow)

Γ ′ , x : A , Γ ′ ′ ⊢ ⋄ Γ ′ , x : A , Γ ′ ′ ⊢ x : A ( Val  x ) \frac{\Gamma', x:A, \Gamma'' \vdash \diamond}{\Gamma', x:A, \Gamma'' \vdash x:A}(\text{Val}\ x) Γ,x:A,Γx:AΓ,x:A,Γ(Val x)

Γ , x : A ⊢ M : B Γ ⊢ λ x : A . M : A → B ( Val Fun ) \frac{\Gamma, x:A \vdash M:B}{\Gamma \vdash \lambda x:A. M: A \to B}(\text{Val Fun}) Γλx:A.M:ABΓ,x:AM:B(Val Fun)

Γ ⊢ M : A → B Γ ⊢ N : A Γ ⊢ M   N : B ( Val Appl ) \frac{\Gamma \vdash M: A \to B \qquad \Gamma \vdash N:A}{\Gamma \vdash M\ N : B}(\text{Val Appl}) ΓM N:BΓM:ABΓN:A(Val Appl)

下面展示一个相当复杂的推导过程,它使用了 F1 的所有规则。

在这里插入图片描述
现在我们已经研究了一个简单的一阶类型系统的基本结构,下面我们将丰富它,使其更接近实际编程语言的类型结构。

我们将为每一个新的类型构造添加一套规则,遵循一个相当有规律的模式。我们从一些基本的数据类型开始:

  • U n i t
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值