类型定义将类型构造器绑定到数据类型:变体类型、记录类型、类型缩写或抽象数据类型。它们还绑定与定义关联的值构造器和记录字段。
|
另请参见以下语言扩展:私有类型、广义代数数据类型、属性、扩展节点、可扩展变体类型 和 内联记录。
类型定义由 type 关键字引入,并由一个或多个简单的定义组成,这些定义可能是相互递归的,并由 and 关键字分隔。每个简单定义都定义一个类型构造器。
一个简单定义由一个小写标识符组成,前面可能带有一个或多个类型参数,后面跟有一个可选的类型等式,然后是一个可选的类型表示,最后是一个约束子句。标识符是被定义的类型构造器的名称。
type colour = | Red | Green | Blue | Yellow | Black | White | RGB of {r : int; g : int; b : int} type 'a tree = Lf | Br of 'a * 'a tree * 'a;; type t = {decoration : string; substance : t'} and t' = Int of int | List of t list
在类型定义的右侧,对其中一个被定义的类型构造器名称的引用被视为递归,除非 type 后面跟着 nonrec。 nonrec 关键字是在 OCaml 4.02.2 中引入的。
可选的类型参数可以是单个类型变量 ' ident(对于带有一个参数的类型构造器),或者是一个类型变量列表 ('ident1,…,'identn)(对于带有多个参数的类型构造器)。每个类型参数都可以以一个方差约束 +(分别为 -)为前缀,表示该参数是协变的(分别为逆变的),以及一个注入性注释 !,表示该参数可以从整个类型中推断出来。这些类型参数可以出现在定义右侧的类型表达式中,也可以通过方差约束来限制;例如,协变参数只能出现在函数箭头的右侧(更准确地说,遵循偶数个箭头的左侧分支),而逆变参数只能出现在左侧(奇数个箭头的左侧分支)。如果类型具有表示或等式,并且参数是自由的(即未通过类型约束绑定到构造类型),则会检查其方差约束,但子类型等将使用参数的推断方差,这可能不那么严格;否则(即对于抽象类型或非自由参数),必须显式给出方差,如果未给出方差,则参数为不变的。
可选的类型等式 = typexpr 使定义的类型等价于类型表达式 typexpr:在类型检查期间可以将一个替换为另一个。如果未给出类型等式,则会生成一个新类型:定义的类型与任何其他类型都不兼容。
可选的类型表示通过给出关联的构造器列表(如果是变体类型)或关联的字段列表(如果是记录类型)来描述表示定义类型的数据结构。如果未给出类型表示,则除了可选类型等式中声明的内容外,不会对类型的结构做出任何假设。
类型表示 = [|] constr-decl { | constr-decl } 描述了一个变体类型。构造器声明 constr-decl1, …, constr-decln 描述与该变体类型关联的构造器。构造器声明 constr-name of typexpr1 * … * typexprn 将名称 constr-name 声明为非常量构造器,其参数的类型为 typexpr1 …typexprn。构造器声明 constr-name 将名称 constr-name 声明为常量构造器。构造器名称必须大写。
类型表示 = { field-decl { ; field-decl } [;] } 描述了一个记录类型。字段声明 field-decl1, …, field-decln 描述与该记录类型关联的字段。字段声明 field-name : poly-typexpr 将 field-name 声明为一个字段,其参数的类型为 poly-typexpr。字段声明 mutable field-name : poly-typexpr 的行为类似;此外,它允许对该字段进行物理修改。不可变字段是协变的,可变字段是不变的。可变和不可变字段都可以具有显式多态类型。每当创建或修改记录值时,都会静态检查内容的多态性。提取的值可以实例化其类型。
类型定义的两个组成部分,可选等式和可选表示,可以独立组合,产生四种典型情况
作为类型参数出现的类型变量可以选择以+或-为前缀,以指示类型构造函数相对于此参数是协变还是逆变。此方差信息用于在检查:>强制转换的有效性时确定子类型关系(请参见第11.7.7节)。
例如,type +'a t声明t为一个抽象类型,在其参数中是协变的;这意味着如果类型τ是类型σ的子类型,则τ t是σ t的子类型。类似地,type -'a t声明抽象类型t在其参数中是逆变的:如果τ是σ的子类型,则σ t是τ t的子类型。如果没有给出+或-方差注释,则假定类型构造函数在相应参数中是非变的。例如,抽象类型声明type 'a t表示如果τ是σ的子类型,则τ t既不是σ t的子类型也不是超类型。
参数上+和-注释指示的方差仅对抽象类型和私有类型强制执行,或者当存在类型约束时强制执行。否则,对于缩写、没有类型约束的变体和记录类型,类型构造函数的方差属性是从其定义推断出来的,并且方差注释仅检查是否符合定义。
注入性注释仅对抽象类型和私有行类型必要,因为否则可以从类型声明中推导出它们:所有参数对于记录和变体类型声明(包括可扩展类型)都是注入的;对于类型缩写,如果参数在其定义等式中具有注入性出现(无论是私有的还是非私有的),则该参数是注入性的。对于类型缩写中的受约束类型参数,如果它们出现在主体中的注入性位置,或者如果它们的类型变量都是注入性的,则它们是注入性的;特别是,如果受约束类型参数包含一个未出现在主体中的变量,则它不可能是注入性的。
构造constraint ' ident = typexpr允许指定类型参数。对应于类型参数ident的任何实际类型参数都必须是typexpr的实例(更准确地说,ident和typexpr被统一)。typexpr的类型变量可以出现在类型等式和类型声明中。
|
异常定义向内置的异常值变体类型exn
添加新的构造函数。构造函数的声明方式与变体类型的定义相同。
表单exception constr-decl生成一个新的异常,与系统中的所有其他异常不同。表单exception constr-name = constr为现有异常提供一个替代名称。