Variants are dual to structs. Whereas structs represent “this and that and the other”, variants represent “this or that or the other”, in other words, alternatives.


We have already met a common variant, the option type:

variant opt[t] =
| None
| Some of t

The names None and Some are sometimes called type constructors. When they’re used to make a value of a variant type, they’re functions, known as injection functions because they inject their argument into the variant type.


Here’s how we can make values of the option type:

var n = None[int];
var s = Some 42;

Notice that for the None case we have to provide the instance type of t, in this case int. For the Some case, the instance int of t is deduced by overload resolution and so can be elided.


Injections are conditionally invertible, that is, the inverses are partial functions which I call extractors. You use these with pattern matches:

fun show (x:opt[int]) =>
  match x with
  | None => "None"
  | Some i => "Some(" + i.str + ")"

Felix “knows” which injection was used to construct a variant value, and selects the matching branch from the match expression. This ensures the extractor is well defined. For the Some branch, the extract sets i to the argument of the injection function used to construct the value.