โ† back to index

Simple Algebraic Data Types

Bartosz Milewski ยท 2015 ยท Category Theory for Programmers, Ch. 6

Prereqs: ๐Ÿž Ch. 5 (Products and Coproducts). 8 min.

Types form a semiring. Product types are multiplication, sum types are addition, Void is 0, Unit is 1. The same algebraic identities you learned in grade school โ€” a ร— 1 = a, a + 0 = a, distributivity โ€” hold for types up to isomorphism. A type definition is an equation you can solve.

A B A × B (product) a AND b tag A | B A + B (sum) a OR b Maybe a = 1 + a: Nothing | Just a

Product types are multiplication

A pair (a, b) is the product of two types. It contains a value of type a and a value of type b. The number of inhabitants of a pair is the product of the inhabitants of each component. Pairs are commutative and associative up to isomorphism, just like multiplication.

Scheme

Records are named products

A record (or struct) is a product type with named fields. Instead of remembering that the first element is the name and the second is the atomic number, you give each field a label. The algebra is the same: it's still multiplication.

Scheme

Sum types are addition

A sum type Either a b holds a value of type a or a value of type b, tagged so you can tell which. The number of inhabitants is the sum. Bool is 1 + 1: two tags, no payload.

Scheme

The algebra: Void is 0, Unit is 1

Void (no inhabitants) is the additive identity: a + 0 โ‰… a. Unit (one inhabitant) is the multiplicative identity: a ร— 1 โ‰… a. Multiplying by Void annihilates: a ร— 0 โ‰… 0. These are the axioms of a semiring.

Scheme

Maybe a = 1 + a

Maybe a is Nothing | Just a, which is 1 + a. It adds one extra value (Nothing) to any type. Maybe Bool has 1 + 2 = 3 inhabitants: Nothing, Just True, Just False. This is Either () a.

Nothing Just a = Unit + a Maybe is the sum of Unit and a โ€” either nothing or something
Scheme

Distributivity: a ร— (b + c) = a ร— b + a ร— c

Products distribute over sums, just like multiplication distributes over addition. A pair of (a, Either b c) is isomorphic to Either (a, b) (a, c). This is a real isomorphism: two functions that are inverses of each other.

Scheme

Lists: solving an equation with types

A list is either empty or a head element followed by a tail list: List a = Nil | Cons a (List a). As an equation: x = 1 + a ร— x. Expand it: x = 1 + a + aยฒ + aยณ + .... A list is either empty (1), one element (a), two elements (aยฒ), three (aยณ), and so on. The algebra predicts the structure.

Scheme

The semiring of types

Putting it all together. Types and their operations satisfy the same laws as natural numbers with addition and multiplication. This is not a metaphor. It's a semiring isomorphism.

Type Algebra Identity Example
Product (A × B)MultiplicationUnit (1)(Int, Bool)
Sum (A + B)AdditionVoid (0)Either Int Bool
Function (A -> B)Exponentiation--Int -> Bool
Scheme

Notation reference

Blog / Haskell Scheme Meaning
Void(no value)Empty type, 0 inhabitants
()'()Unit type, 1 inhabitant
(a, b)(list a b)Product type
Either a b(list 'left a) | (list 'right b)Sum type
Maybe a'nothing | (list 'just x)Optional, 1 + a
data Bool = True | False#t | #f1 + 1 = 2
[a](list ...)List a = 1 + a ร— List a
Neighbors

Milewski chapters

Foundations (Wikipedia)

Translation notes

The blog post uses Haskell algebraic data types and C++ structs/unions. This page uses Scheme tagged lists for sum types and plain lists for product types. The key insight translates directly: counting inhabitants of a type follows the same arithmetic as the type's algebraic expression. Haskell enforces these types at compile time; Scheme relies on tagging conventions. The algebra is the same either way.

Ready for the real thing? Read the blog post. The semiring table is in the middle. The list equation at the end is worth staring at.