Chapter 10 Language extensions

14 Extensible variant types

(Introduced in OCaml 4.02)

type-representation::= ...
 =..
 
specification::= ...
 type [type-params] typeconstrtype-extension-spec
 
definition::= ...
 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
 

Extensible variant types are variant types which can be extended with new variant constructors. Extensible variant types are defined using ... New variant constructors are added using +=.

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

Pattern matching on an extensible variant type requires a default case to handle unknown variant constructors:

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

A preexisting example of an extensible variant type is the built-in exn type used for exceptions. Indeed, exception constructors can be declared using the type extension syntax:

type exn += Exc of int

Extensible variant constructors can be rebound to a different name. This allows exporting variants from another module.

# let not_in_scope = Str "Foo";;
Error: Unbound constructor Str
type Expr.attr += Str = Expr.Str
# let now_works = Str "foo";;
val now_works : Expr.attr = Expr.Str "foo"

Extensible variant constructors can be declared private. As with regular variants, this prevents them from being constructed directly by constructor application while still allowing them to be de-structured in pattern-matching.

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: Cannot use private constructor Bool to create values of type Expr.attr

14.1 Private extensible variant types

(Introduced in OCaml 4.06)

type-representation::= ...
 =private..
 

Extensible variant types can be declared private. This prevents new constructors from being declared directly, but allows extension constructors to be referred to in interfaces.

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