第 11 章 OCaml 语言

4 类型表达式

typexpr::= '标识符
 _
 (typexpr)
  [[?]标签名:] typexpr->typexpr
 typexpr { *typexpr }+
 typeconstr
 typexprtypeconstr
 (typexpr { ,typexpr } )typeconstr
 typexpras'标识符
 多态变体类型
 < [..] >
 <方法类型 { ;方法类型 } [; ∣ ;..] >
 #类类型路径
 typexpr#类路径
 (typexpr { ,typexpr } )#类路径
 
多态类型表达式::= typexpr
  { '标识符 }+.typexpr
 
方法类型::= 方法名:多态类型表达式

另请参阅以下语言扩展:一等模块属性扩展节点

下表显示了运算符和非封闭类型构造的相对优先级和结合性。优先级较高的构造首先出现。

运算符结合性
类型构造函数应用
#
*
->右结合
as

类型表达式表示数据类型定义中的类型以及模式和表达式上的类型约束。

类型变量

类型表达式 ' 标识符 代表名为 标识符 的类型变量。类型表达式 _ 代表匿名类型变量或匿名类型参数。在数据类型定义中,类型变量是数据类型参数的名称。在类型约束中,它们表示未指定的类型,可以通过任何类型实例化以满足类型约束。通常,命名类型变量的作用域是其出现的整个顶级短语,并且只有在离开此作用域时才能对其进行泛化。匿名变量没有此类限制。在以下情况下,命名类型变量的作用域限制在其出现的类型表达式中:1) 对于通用(显式多态)类型变量;2) 对于仅出现在公共方法规范中的类型变量(因为这些变量将被设为通用,如第 ‍11.9.1 节所述);3) 对于用作别名的变量,当它们所引用的类型在封闭定义的作用域中无效时( 当它包含自由通用类型变量或局部定义的类型时)。

带括号的类型

类型表达式 ( typexpr ) 表示与 typexpr 相同的类型。

函数类型

类型表达式 typexpr1 -> typexpr2 表示函数的类型,该函数将类型为 typexpr1 的参数映射到类型为 typexpr2 的结果。

标签名 : typexpr1 -> typexpr2 表示相同的函数类型,但参数被标记为 标签

? 标签名 : typexpr1 -> typexpr2 表示函数的类型,该函数将类型为 typexpr1 的可选标记参数映射到类型为 typexpr2 的结果。也就是说,函数的物理类型将为 typexpr1 option -> typexpr2

元组类型

类型表达式 typexpr1 ** typexprn 表示元组的类型,其元素分别属于类型 typexpr1、… typexprn

构造类型

没有参数的类型构造函数,如 typeconstr,是类型表达式。

类型表达式 typexpr typeconstr,其中 typeconstr 是一个带有一个参数的类型构造函数,表示将一元类型构造函数 typeconstr 应用于类型 typexpr

类型表达式 (typexpr1,…,typexprn) typeconstr,其中 typeconstr 是一个带 n 个参数的类型构造函数,表示将 n 元类型构造函数 typeconstr 应用于类型 typexpr1typexprn

在类型表达式 _ typeconstr 中,匿名类型表达式 _ 代表匿名类型参数,等效于 (_, …,_),其中 _ 的重复次数与 typeconstr 的元数相同。

带别名和递归的类型

类型表达式 typexpr as ' 标识符 表示与 typexpr 相同的类型,并且还在 typexpr 和其他类型中将类型变量 标识符 绑定到类型 typexpr。通常,别名的作用域与命名类型变量的作用域相同,涵盖整个封闭定义。如果类型变量 标识符 实际上出现在 typexpr 中,则会创建一个递归类型。对于存在不包含对象或多态变体类型构造函数的递归路径的递归类型,将被拒绝,除非选择了 -rectypes 模式。

如果 ' 标识符 表示显式多态变量,并且 typexpr 表示对象或多态变体类型,则 typexpr 的行变量将被 ' 标识符 捕获并进行量化。

多态变体类型

多态变体类型::= [tag-spec-first { |tag-spec } ]
 [> [ tag-spec ] { |tag-spec } ]
 [< [|] tag-spec-full { |tag-spec-full } [ > { `tag-name }+ ] ]
 
tag-spec-first::= `tag-name [ oftypexpr ]
  [ typexpr ] |tag-spec
 
tag-spec::= `tag-name [ oftypexpr ]
 typexpr
 
tag-spec-full::= `tag-name [ of [&] typexpr { &typexpr } ]
 typexpr

多态变体类型描述了多态变体可能取的值。

第一种情况是精确变体类型:所有可能的标签都是已知的,以及它们关联的类型,并且它们都可能存在。其结构是完全已知的。

第二种情况是开放变体类型,描述了一个多态变体值:它给出了该值可能取的所有标签的列表,以及它们关联的类型。此类型仍然与包含更多标签的变体类型兼容。一个特例是未知类型,它不定义任何标签,并且与任何变体类型兼容。

第三种情况是闭合变体类型。它提供了所有可能的标签及其关联类型的相关信息,以及哪些标签已知可能出现在值中。精确变体类型(第一种情况)只是闭合变体类型的简写,其中所有可能的标签也可能存在。

在这三种情况下,标签都可以直接在`tag-name [of typexpr] 形式中指定,也可以通过类型表达式间接指定,该表达式必须扩展为精确变体类型,其标签规范将插入其位置。

变体标签的完整规范仅用于非精确闭合类型。它们可以理解为参数的合取类型:它旨在具有规范中枚举的所有类型。

这种合取约束可能是不可满足的。在这种情况下,相应的标签可能不会在此类型的变量中使用。这并不意味着整个类型无效:仍然可以使用其他可用标签。合取约束主要用于类型检查器的输出。当它们在源程序中使用时,不可解的约束可能会导致早期错误。

对象类型

对象类型< [method-type { ; method-type }] >是方法类型的记录。

每个方法都可以具有显式的多态类型:{ ' ident }+ . typexpr。显式多态变量具有局部作用域,并且显式多态类型只能统一为等价的类型,其中只有多态变量的顺序和名称可能发生变化。

类型< { method-type ; } .. >是对象的类型,其方法名称和类型由method-type1, …, method-typen描述,以及可能由省略号表示的一些其他方法。此省略号实际上是一种特殊的类型变量(在文献中称为行变量),代表任意数量的额外方法类型。

#-类型

类型# classtype-path是一种特殊的缩写。此缩写与属于类类型classtype-path的子类的任何对象的类型统一。它以特殊的方式处理,因为它通常隐藏一个类型变量(省略号,表示可能在子类中添加的方法)。特别是,当省略号被实例化时,它会消失。每个类型表达式# classtype-path定义一个新的类型变量,因此类型# classtype-path -> # classtype-path通常与类型(# classtype-path as ' ident) -> ' ident不同。

变体和记录类型

没有描述(定义)变体类型或记录类型的类型表达式,因为这些类型始终是命名的,即在使用前定义并通过名称引用。类型定义在第 ‍11.8.1节中描述。