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 = structtype 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 : sigtype Expr.attr += private Bool of int
val bool : bool -> Expr.attr
end = structtype 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
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 : sigtype t = private ..
module MkConstr (X : sigtype t end) : sigtype t += C of X.t
endend = structtype t = ..
module MkConstr (X : sigtype t end) = structtype t += C of X.t
endend