依赖类型
在计算机科学和逻辑中,依赖类型(或依值类型,dependent type)是指依赖于值的类型,其理论同时包含了数学基础中的类型论和计算机编程中用以减少程序错误的类型系统两方面。在 Per Martin-Löf 的直觉类型论中,依赖类型可对应于谓词逻辑中的全称量词和存在量词;在依赖类型函数式编程语言如ATS、Agda、Dependent ML、Epigram、F*和Idris中,依赖类型系统通过极其丰富的类型表达能力使得程序规范得以借助类型的形式被检查,从而有效减少程序错误。
類型系統 |
---|
一般概念 |
主要分类 |
次要分类 |
依赖类型的两个常见实例是依赖函数类型(又称依赖乘积类型、Π-类型)和依赖值对类型(又称依赖总和类型、Σ-类型)。一个依赖类型函数的返回值类型可以依赖于某个参数的具体值,而非仅仅参数的类型,例如,一个输入参数为整型值n的函数可能返回一个长度为n的数组;一个依赖类型值对中的第二个值可以依赖于第一个值,例如,依赖类型可表示这样的类型:它由一对整数组成,其中的第二个数总是大于第一个数。
依赖类型增加了类型系统的复杂度。由于确定两个依赖于值的类型的等价性需要涉及具体的计算,若允许在依赖类型中使用任意值的话,其类型检查将会成为不可判定问题;换言之,无法确保程序的类型检查一定会停机。
由于Curry-Howard同构揭示了程序语言的类型论与证明论的直觉逻辑之间的紧密关联性,以依赖类型系统为基础的编程语言大多同时也作为构造证明与可验证程序的辅助工具而存在,如 Coq 和 Agda(但并非所有证明辅助工具都以类型论为基础);近年来,一些以通用和系统编程为目的的编程语言被设计出来,如 Idris。
一些以证明辅助为主要目的的编程语言采用强函数式编程(total functional programming),这消除了停机问题,同时也意味着通过它们自身的核心语言无法实现任意无限递归,不是图灵完全的,如 Coq 和 Agda;另外一些依赖类型编程语言则是图灵完全的,如 Idris、由 ML 衍生而来的 ATS 和 由 F# 衍生而来的 F*。
形式化定义
Π-类型
在全类(论域中全部类型构成的类型) 中给定一个类型 ,存在着类型族 为每一项 赋予一个类型 。一个值域依赖于其参数的函数,称之为一个依赖类型函数,该函数的类型则称之为依赖类型、依赖乘积类型或Π-类型。在此例子中,依赖类型可以写作
或
若B为常数,则依赖类型退化成一般形态的函数 。即 等价于函数类型 。
被称之为“Π-类型”的原因是它可以被看作是类型的笛卡尔积。Π-类型同时也可被看作是全称量词的模型。
例如,表示实数的-元组类型,则 表示这样的函数类型:给定一个自然数n,该函数返回一个大小为n的实数元组。一般的函数空间可以看作依赖型函数的一个特例,当函数返回值类型实质上并不依赖于输入时,如 即为从自然数到实数的函数类型,它可以在简单类型lambda演算中被写作 。
多态是依赖类型函数的一个重要实例。给定一个类型,函数作用于该类型的元素之上。一个返回元素类型为C的多态函数可能拥有如下的多态类型:
Lambda 立方
Henk Barendregt 提出了 Lambda 立方模型,用于对不同的类型系统的表达能力加以区分。Lambda 立方的八个顶点分别对应各自的类型系统,简单类型lambda演算位于表达能力最低的顶点上,而构造演算(calculus of constructions)则位于表达能力最强的顶点上。
一阶依赖类型
一阶依赖类型 ,对应于逻辑框架 LF,是通过把简单类型lambda演算的函数空间一般化为依赖乘积类型而获得的。
二阶依赖类型
二阶依赖类型 ,通过允许对 类型构造子的量化得到。此时,依赖乘积类型涵括了简单类型lambda演算中的与 系统F 中的。
依赖类型编程语言
语言 | 是否活跃开发中 | 范式[脚注 1] | 策略(tactics) | 证明项 | 终止检查 | 类型允许依赖于[脚注 2] | 全类 | 证明无关性 | 是否支持程序抽取 | 程序抽取是否消除无关项 |
---|---|---|---|---|---|---|---|---|---|---|
Agda | 是[2] | 纯函数式 | 少且有限[脚注 3] | 是 | 是(可选) | 任意项 | 是(可选)[脚注 4] | 证明无关性参数[4] | Haskell、JavaScript | 是[4] |
ATS | 是[5] | 函数式 / 命令式 | 否[6] | 是 | 是 | ? | ? | ? | 是 | ? |
Cayenne[7] | 否 | 纯函数式 | 否 | 是 | 否 | 任意项 | 否 | 否 | ? | ? |
Gallina(Coq) | 是[8] | 纯函数式 | 是 | 是 | 是 | 任意项 | 是[脚注 5] | 否 | Haskell、Scheme、OCaml | 是 |
Dependent ML | 否[脚注 6] | ? | ? | 是 | ? | 自然数 | ? | ? | ? | ? |
Guru[9] | 否[10] | 纯函数式[11] | hypjoin[12] | 是[11] | 是 | 任意项 | 否 | 是 | Carraway | 是 |
Idris | 是[13] | 纯函数式[14] | 是[15] | 是 | 是(可选) | 任意项 | 是 | 否 | 是 | 是[15] |
Matita | 是[16] | 纯函数式 | 是 | 是 | 是 | 任意项 | 是 | 是 | OCaml | 是 |
Nuprl | 是 | 纯函数式 | 是 | 是 | 是 | 任意项 | 是 | ? | 是 | ? |
F* | 是 | 函数式 / 命令式 | ? | ? | ? | ? | ? | ? | ? | ? |
PVS | 是 | ? | 是 | ? | ? | ? | ? | ? | ? | ? |
Sage[17] | ? | 混合类型检查 | ? | ? | ? | ? | ? | ? | ? | ? |
Twelf | 是 | 逻辑式 | ? | 是 | 是(可选) | 任意(LF)项 | 否 | 否 | ? | ? |
脚注
参考文献
- . [2019-04-12]. (原始内容存档于2020-11-11).
- . [2014-08-24]. (原始内容存档于2019-06-27).
- . [2014-08-24]. (原始内容存档于2009-04-17).
- . [2014-08-24]. (原始内容存档于2011-07-18).
- . [2014-08-24]. (原始内容存档于2012-03-02).
- . [2014-08-24]. (原始内容存档于2013-02-04).
- Augustsson, Lennart. . ICFP '98. Proceedings of the third ACM SIGPLAN international conference on Functional programming. 1998: 239–250. CiteSeerX 10.1.1.47.155 . S2CID 18331937. doi:10.1145/289423.289451 .
- . [2014-08-24]. (原始内容存档于2018-09-29).
- Guru (页面存档备份,存于)
- . [2014-08-24]. (原始内容存档于2015-11-18).
- Aaron Stump. (PDF). 6 April 2009 [28 September 2010]. (原始内容 (PDF)存档于2009年12月29日).
- Adam Petcher. (PDF). 1 April 2008 [14 October 2010]. (原始内容存档 (PDF)于2010-07-19).
- .
- (PDF). [2014-08-24]. (原始内容 (PDF)存档于2011-07-16).
- Edwin Brady. .
- . [2014-08-24]. (原始内容存档于2006-05-08).
- Sage (页面存档备份,存于)