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#myvariant
is equivalent to writing(`Tag1(_ : int) | `Tag2(_ : bool))
.