第 12 章 语言扩展

14 可扩展变体类型

(在 OCaml 4.02 中引入)

类型表示::= ...
 =..
 
规范::= ...
 type [type-params] typeconstrtype-extension-spec
 
定义::= ...
 type [type-params] typeconstrtype-extension-def
 
type-extension-spec::=+= [private] [|] constr-decl { |constr-decl }
 
type-extension-def::=+= [private] [|] constr-def { |constr-def }
 
constr-def::= constr-decl
 constr-name=constr
 

可扩展变体类型是可以扩展新变体构造器的变体类型。可扩展变体类型使用 .. 定义。使用 += 添加新的变体构造器。

module Expr = struct type attr = .. type attr += Str of string type attr += | Int of int | Float of float end

对可扩展变体类型进行模式匹配需要一个默认情况来处理未知的变体构造器。

let to_string = function | Expr.Str s -> s | Expr.Int i -> Int.to_string i | Expr.Float f -> string_of_float f | _ -> "?"

可扩展变体类型的一个预先存在的示例是用于异常的内置 exn 类型。实际上,可以使用类型扩展语法声明异常构造器。

type exn += Exc of int

可扩展变体构造器可以重新绑定到不同的名称。这允许从另一个模块导出变体。

# let not_in_scope = Str "Foo";;
Error: 未绑定的构造器 Str
type Expr.attr += Str = Expr.Str
# let now_works = Str "foo";;
val now_works : Expr.attr = Expr.Str "foo"

可扩展变体构造器可以声明为 private。与常规变体一样,这可以防止它们通过构造器应用直接构造,同时仍然允许在模式匹配中对其进行解构。

module B : sig type Expr.attr += private Bool of int val bool : bool -> Expr.attr end = struct type Expr.attr += Bool of int let bool p = if p then Bool 1 else Bool 0 end
# let inspection_works = function | B.Bool p -> (p = 1) | _ -> true;;
val inspection_works : Expr.attr -> bool = <fun>
# let construction_is_forbidden = B.Bool 1;;
Error: 无法使用私有构造器 Bool 创建 Expr.attr 类型的值

14.1 私有可扩展变体类型

(在 OCaml 4.06 中引入)

类型表示::= ...
 =private..
 

可扩展变体类型可以声明为 private。这可以防止直接声明新的构造器,但允许在接口中引用扩展构造器。

module Msg : sig type t = private .. module MkConstr (X : sig type t end) : sig type t += C of X.t end end = struct type t = .. module MkConstr (X : sig type t end) = struct type t += C of X.t end end