Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Algebraic Data Types (ADTs)

ADTs let you define your own sum types.

You’ll use ADTs to model “this or that” choices: optional values, tagged unions, trees, results, etc.

Simple ADT

type Maybe a = Just a | Nothing

Constructors are values:

type Maybe a = Just a | Nothing

let v = Just 1 in
  (v, Nothing)

Using ADTs is all about match

Defining an ADT is only half the story; consuming it is done with pattern matching:

type Maybe a = Just a | Nothing

let
  fromMaybe = \d m ->
    match m
      when Just x -> x
      when Nothing -> d
in
  fromMaybe 0 (Just 5)

Constructors with multiple fields

type Pair a b = Pair a b

let v = Pair 1 "hi" in
  v

This is a single-constructor ADT (a “product type”). In many programs you’ll use record-carrying constructors instead because they self-document field names.

Record-carrying constructors

Variants can carry a record payload:

type User = User { name: string, age: i32 }

let u = User { name = "Ada", age = 36 } in
  u

This style works well with field projection and update (covered later).

Multi-variant and recursive ADTs

You can define sum types with multiple constructors, including recursive ones:

type Tree
  = Leaf { value: i32 }
  | Node { left: Tree, right: Tree }

Recursive ADTs are the foundation for ASTs, expression trees, and many structured data problems.