Polymorphic Variants
Polymorphic variants start with a backtick and don't need a type declaration:
26.1 Syntax
Polymorphic variants start with a backtick and don't need a type declaration:
let color_to_int = function
| `Red -> 0
| `Green -> 1
| `Blue -> 2
(* val color_to_int : [< `Blue | `Green | `Red ] -> int *)
let x = `Point (1, 2) (* [> `Point of int * int ] *)26.2 Open and closed types
[ \A | \B ] exactly A or B [> \A | \B ] at least A and B (open — can be extended) [< \A | \B ] at most A and B (subset)
[< \A | \B > \A ]` | at most A,B; at least A
26.3 Declaring and combining
type basic = [ `Red | `Green | `Blue ]
type extended = [ basic | `Black | `White ]
let to_string : [< extended ] -> string = function
| #basic -> "basic color" (* #basic matches any basic constructor *)
| `Black -> "black"
| `White -> "white"26.4 Subtyping and coercion
let b : basic = `Red
let e : extended = (b :> extended)26.5 Use cases
Composable error types: [ \Not_found | \Permission_denied ] merged across libraries.
Lightweight enumerations, tagging, HTTP methods in web libraries.
let read_file path : (string, [> `Not_found of string ]) result = ...
let parse s : (int, [> `Parse_error ]) result = ...
(* Using both in one function yields [> `Not_found of string | `Parse_error ] automatically *)26.6 Trade-offs
Pros: flexible, extensible, no declarations. Cons: worse error messages, typos create new tags, less exhaustiveness help when open. Prefer regular variants unless you need the flexibility.