Part IA Michaelmas Term
Constructors with Arguments
Carrying data
OCaml generalises enumeration types by allowing constructors to carry data:
type vehicle = Bike
| Motorbike of int (* engine size in CCs *)
| Car of bool (* true if a Reliant Robin *)
| Lorry of int (* number of wheels *)
Bikeis a constant constructor: it is a value by itself.Motorbike 450is a vehicle constructed from the integer 450.Car trueandCar falseare distinct vehicles from the same constructor.Motorbike of intandLorry of intare distinct types: even though both carry anint, OCaml tracks which constructor was used.Motorbike 450is never confused withLorry 450.
Pattern matching with arguments
Constructors carrying data can be destructured in patterns:
let wheels = function
| Bike -> 2
| Motorbike _ -> 2 (* discard the engine size *)
| Car robin -> if robin then 3 else 4 (* bind to robin *)
| Lorry w -> w (* extract the wheel count *)
Pattern elements:
- Named variable (
robin,w): binds the carried value for use in the right-hand side. - Wildcard
_: matches any carried value and discards it. The underscore signals that the argument is irrelevant to the computation.
Mixed-type-like lists
Datatypes with constructors carrying different payload types allow heterogeneous collections:
[Bike; Car true; Motorbike 450]
This is a vehicle list. It behaves almost like a mixed-type list containing integers and booleans. The datatype mechanism reduces the impact of the restriction that all list elements must share the same type.
Nested patterns
Patterns can be as complex as needed and may combine constructors from multiple datatypes. For example, patterns can deconstruct lists and vehicles simultaneously, or match integer and string constants inside constructors. OCaml compiles pattern matching efficiently.