Overview

Modern programming languages provide structured data through records and variants.
Records capture fixed labeled collections of values; variants encode distinct alternatives.
Together, they form the foundation for algebraic data types (ADTs) and safe pattern matching.

Note

Records = product types (fields combined).
Variants = sum types (one alternative active).
Pattern matching = selective decomposition of those structures.


Records: Product Structures

A record groups labeled fields together into one value.
Unlike tuples, fields are identified by names rather than position.

Example (OCaml):

type point = { x: float; y: float }
 
let move p dx dy = { x = p.x +. dx; y = p.y +. dy }

Records make code more self-documenting and robust to field reordering.

ConceptTupleRecord
Identificationby positionby label
Extensibilityrigidflexible (with optional defaults)
Example(1.0, 2.0){x=1.0; y=2.0}

Tuple vs record access semantics


Variants: Sum Structures

A variant (also called a tagged union) represents a value that can take one of several labeled forms.

Example:

type shape =
  | Circle of float
  | Square of float
  | Rectangle of float * float

Each constructor (Circle, Square, Rectangle) tags its data.
The compiler tracks which variant is active at runtime.

Note

Variants correspond to sum types:
Shape = Circle(radius) + Square(side) + Rectangle(width,height).

Variants can be nested, parameterized, or recursive — enabling expressive hierarchies like:

type 'a tree = Leaf | Node of 'a * 'a tree * 'a tree

Pattern Matching

Pattern matching destructures values according to their constructors or record fields.

Example:

let area s =
  match s with
  | Circle r -> Float.pi *. r *. r
  | Square a -> a *. a
  | Rectangle (w, h) -> w *. h

Each clause tests the constructor and binds its contents to names.
Pattern matching replaces chains of conditionals with a concise, declarative form.

Tip

Matching is exhaustive and typed — every case is checked for consistency by the compiler.


Nested and Guarded Patterns

Patterns can be nested or combined with guards for finer control:

match s with
| Rectangle (w, h) when w = h -> "square"
| Rectangle _ -> "rectangle"
| Circle _ -> "circle"

Guards (when ...) allow conditional matching beyond constructor names.
Nested patterns can directly decompose structures:

match node with
| Node (x, Leaf, _) -> x
| Node (_, l, r) -> traverse l; traverse r
| Leaf -> ()

Exhaustiveness and Redundancy

Compilers perform exhaustiveness checking to ensure that every possible variant is handled.
They also warn about redundant (unreachable) patterns.

Example:

match s with
| Circle r -> r*r
| _ -> 0  (* covers all remaining variants *)

Warning

Non-exhaustive matches cause runtime errors in many languages.
Some, like Haskell and OCaml, statically detect missing cases and issue warnings.

Pattern match exhaustiveness analysis


Record Patterns

Pattern matching also works on record fields:

match p with
| { x; y } when x = y -> "diagonal"
| { x; y } -> "non-diagonal"

Each field can be selectively matched or ignored:

| { x; _ } -> x

Renaming is allowed during binding:

| { x = x_pos; y = y_pos } -> (x_pos, y_pos)

Note

Partial record patterns are permitted — unmentioned fields are ignored.


Variants with Parameters

Constructors can carry arbitrary payloads:

type value =
  | Int of int
  | Float of float
  | Pair of value * value

Each case introduces new bindings during a match:

match v with
| Int n -> string_of_int n
| Pair (a, b) -> "(" ^ show a ^ ", " ^ show b ^ ")"

This recursive style forms the basis of interpreters, compilers, and type checkers.


Design Pitfalls

Warning

  • Missing constructors → non-exhaustive matches.

  • Shadowed patterns → redundant code that never executes.

  • Variant misuse → applying the wrong constructor or mismatched arguments.

  • Overly broad _ patterns → suppress exhaustiveness checking, hiding bugs.

Tip

Treat _ as a temporary placeholder during prototyping — replace it with explicit cases for maintainability.


Conceptual Summary

ConceptDescriptionExample
RecordLabeled product of values{x=1; y=2}
VariantTagged alternative forms`Circle r
Pattern MatchStructured deconstructionmatch s with ...
ExhaustivenessAll cases handledcompiler check
GuardsConditional refinementwhen w = h

See also