Polymorphic variants
Pattern matching polymorphic variants has some extra capabilities that you should be aware of. This occurs in the compilers starting from assignment 3 when operators are defined in terms of different polymorphic variant types:
type base_op = [
| `Read
| `Add
| `Sub
| `Negate
| `Not
]
type cmp_op = [
| `Eq
| `Lt
| `Le
| `Gt
| `Ge
]
type core_op = [
| base_op
| cmp_op
]
As you can see, you can define core_op as the union
of two other polymorphic variant types
without defining a new constructor.
(This is something you can't do with regular algebraic datatypes.)
But when you are pattern-matching on core_op values
(which can have any of the constructors of base_op or cmp_op)
you may need to split them back into the two classes.
This is done rather easily:
match (op : core_op) with (* type annotation is optional *)
| #base_op as b_op -> (* your code with (b_op : base_op) *)
| #cmp_op as c_op -> (* your code with (c_op : cmp_op) *)
The new syntax #base_op as b_op (or #cmp_op as c_op)
will match any of the base_op (or cmp_op) constructors,
and you can then do whatever you want with those.
This is described (somewhat briefly) in the OCaml manual:
To make this even more comfortable, you may use type definitions as abbreviations for or-patterns. That is, if you have defined
type myvariant = [`Tag1 of int | `Tag2 of bool], then the pattern#myvariantis equivalent to writing(`Tag1(_ : int) | `Tag2(_ : bool)).