Ship

Lexicon · Variant
On this page · 1 section

Variant

A variant is a tagged choice type. Ship has two, differing only by one knob — whether the set of cases is fixed (nominal) or extensible (structural):

Closed variantOpen variant
Set of casesfixed, nominalextensible, structural
Declared`type Status = \Open \Done`no declaration needed
Case syntaxPascalCase constructors (Open, Done(T)):tags (:ok, :error(T))
Built fromconstructor lista row of tags
Default?yes — boring default for domain modelingopt in for structural composition
// closed variant — nominal, fixed
type Status = | Open | Done

// open variant — structural, extensible, built from a row of tags
let x: [ :ok | :error(String) ] = :ok

OCaml calls the open variant a polymorphic variant; "open variant" is the canonical Ship name. The nominal one is sometimes called an ADT (algebraic data type) — prefer "closed variant" in Ship prose.

How the pieces fit

  • A tag (:foo) is one case of an open variant.

  • A row is the set of tags; wrap it in [ … ] to get an open variant type. A row is the ingredient; the open variant is the finished type.

  • Polymorphic open-variant parameters use the open-binder (open 'r): type Timed(open 'r) = [ 'r | :timeout(Duration) ].

  • The error channel is a row of tags too — see error-row.md.

  • A row only exists at kind Row; a finished variant is at kind Type.

    See open-variant.md, row.md, tag.md, kind.md, and ../01-syntax.md.