A Simple Value
In OCaml, let binds a name to a value. Here we start with a simple string describing a shape. The compiler infers its type as string automatically.
Defining a Variant Type
Algebraic data types are OCaml's secret weapon. Each variant constructor carries its own payload — Circle holds a radius, Rectangle holds width and height.
Think of it as an enum where each case can hold different shaped data.
Your First Pattern Match
The match expression destructures values by shape. Each arm binds variables and computes a result. If you forget a case, the compiler warns you.
This is exhaustiveness checking — one of OCaml's most powerful safety features.
Extending the Type
Need a new shape? Add a variant to the type and a new match arm. The compiler will flag every match that doesn't handle the new case.
This makes refactoring fearless — the type system guides you to every spot that needs updating.
Guards for Edge Cases
A when guard adds a boolean condition to a pattern arm. Here we catch degenerate shapes with zero or negative dimensions before the normal calculation.
Guards combine structural matching with arbitrary logic — powerful and readable.
Higher-Order Functions
Finally, we build a list of shapes and List.map our area function across all of them. Functions are first-class — pass them around like any other value.
Pattern matching, variants, and higher-order functions: the OCaml trifecta.