English for OCaml Developers

Vocabulary for developers working in OCaml — algebraic data types, pattern matching exhaustiveness, the module system, and functor talk for functional teams.

OCaml conversations lean heavily on precise type-system vocabulary, because the language’s whole value proposition is catching bugs at compile time through types most mainstream languages don’t have. Discussing OCaml code without this vocabulary means falling back on vague terms like “the type thing” for concepts your teammates need named exactly.

Key Vocabulary

Algebraic data type (ADT) — a type built by combining other types either as a product (a record with several fields, all present at once) or a sum (a variant, exactly one of several possible shapes), the foundation of how OCaml models data. “Model this as an algebraic data type instead of a record with a bunch of optional fields — a variant makes illegal states literally unrepresentable, so you can’t end up with a Paid order that also has a null amount.”

Exhaustiveness checking — the compiler’s verification that a pattern match covers every possible constructor of a variant, refusing to compile (or at least warning) if a case is missing, which is how OCaml prevents a whole class of “forgot to handle this case” bugs. “Add the new Refunded case to the variant and let exhaustiveness checking do its job — every match expression handling OrderStatus will now fail to compile until you’ve updated it, so we can’t ship this half-handled.”

Functor — in OCaml specifically, a module that takes another module as a parameter and produces a new module, distinct from the mathematical or Haskell sense of the word, used for building generic, reusable module-level abstractions. “We wrote this as a functor parameterized over the comparison module, so the same balanced-tree implementation works for any orderable key type without duplicating the tree logic.”

Module signature (.mli file) — an explicit interface file declaring exactly which types and values a module exposes, hiding everything else, giving you compiler-enforced encapsulation that isn’t just a naming convention. “Don’t expose the internal helper function — leave it out of the .mli, and the module signature will enforce that callers genuinely can’t reach it, not just that they’re not supposed to.”

Polymorphic variant — an open, structurally-typed variant (written with a leading backtick) that doesn’t need to be declared upfront in a single type definition, trading some of the safety of ordinary variants for more flexibility across module boundaries. “We used a polymorphic variant here on purpose, since this function needs to accept results from three unrelated modules without those modules all depending on one shared variant type.”

Common Phrases

  • “Is this modeled as an algebraic data type, or are we tracking valid states with booleans and hoping for the best?”
  • “Does exhaustiveness checking catch this, or did we silence the warning somewhere?”
  • “Should this be a functor, so it’s reusable across module types, or is one concrete implementation enough?”
  • “Is that value exposed in the module signature, or is it meant to stay internal?”
  • “Do we actually need a polymorphic variant here, or would an ordinary variant be safer?”

Example Sentences

Explaining a design choice in review: “I modeled the payment state as an algebraic data type instead of a struct with a status string and three optional fields — now a Refunded payment simply can’t have a null refundedAt, because the variant constructor requires it.”

Flagging a risky pattern match: “This match isn’t exhaustive — the compiler’s only warning because we’ve got a wildcard case swallowing everything, which means a new variant case added later would silently fall into that wildcard instead of failing the build.”

Describing a module design: “We wrote the cache as a functor over the key module, so the same eviction logic gets reused for string keys, integer keys, and our custom OrderId type without three separate implementations.”

Professional Tips

  • Reach for an algebraic data type whenever you’re tempted to represent state with a combination of booleans or nullable fields — it’s the idiomatic OCaml way to make invalid states unrepresentable, and reviewers will expect it.
  • Never silence an exhaustiveness checking warning with a blanket wildcard case unless you’ve deliberately decided new cases should be ignored by default — that decision needs to be explicit and reviewed, not accidental.
  • Use a functor when you have real, structural reuse across module types, not just superficial similarity — overusing functors makes code harder to read than the duplication it was meant to avoid.
  • Keep the module signature minimal and intentional — treat the .mli file as the actual contract you’re reviewing, since it’s what other engineers depend on, not the implementation file.
  • Default to ordinary variants over polymorphic variants unless you specifically need the structural flexibility — polymorphic variants trade compiler help for flexibility, and that trade should be a conscious one.

Practice Exercise

  1. Explain the difference between an algebraic data type and a plain record with optional fields.
  2. Describe why exhaustiveness checking matters when a new variant case gets added later.
  3. Write a sentence justifying the use of a functor over duplicating an implementation.

Frequently Asked Questions

What English level do I need to read "English for OCaml Developers"?

This article is tagged Advanced. If you find the vocabulary difficult, start with a related Vocabulary vocabulary exercise first, then come back — technical reading gets much easier once the core terms feel familiar.

Is this article free to read?

Yes. Every article on CoderSlingo, including this one, is free to read with no account, sign-up, or paywall.

How is reading this article different from doing an exercise?

Articles like this one explain concepts and vocabulary in context through prose, while exercises are interactive drills — fill-in-the-blank, matching, and multiple-choice — that test and reinforce specific terms. Reading builds understanding; exercises build recall.