wiki

Polymorphic variant

also: polymorphic variants, open variant, row type

A variant whose constructors, called tags and written with a backquote, exist independently of any type declaration. Their types are sets of tags with bounds: [> `A] means at least `A, [< `A | `B] at most those two, and unification works out unions and intersections of those sets.

An ordinary variant constructor belongs to exactly one type, the one that declared it. A tag like `Zero belongs to no declaration, so any function can produce or consume it, and the type checker tracks which tags a value might carry and which a function can accept.

Consuming gives an upper bound, producing a lower one.

let to_int = function `Zero -> 0 | `Succ n -> n + 1
let zero = `Zero

What ocamlc -i infers, OCaml 5.5.1.

val to_int : [< `Succ of int | `Zero ] -> int
val zero : [> `Zero ]

Passing zero to to_int unifies [> `Zero ] with [< `Succ of int | `Zero ], which succeeds because the tag the value might carry is one the function accepts. Passing a `Minus would fail at compile time, with the tag named in the error.

The same machinery works as a type-level set with no values at all: a phantom parameter can be an open polymorphic variant, so that unifying two of them computes a union. Error messages are longer than for ordinary variants, and a typo in a tag inside an open type is not caught where it is written, which is why most code keeps them for the places that need the openness.

see also

referenced by

further reading

  • J. Garrigue, “Programming with polymorphic variants”, ML Workshop (1998).
  • J. Garrigue, “Code reuse through polymorphic variants”, Workshop on Foundations of Software Engineering (2000).