Algebraic Data Types for C99

Appeal of ADTs and pattern matching

  • Many commenters say algebraic data types (ADTs) with pattern matching feel “obviously right” once used (e.g., Haskell, F#, OCaml, Rust, Erlang, Elm, Swift, Scala, Kotlin).
  • Benefits cited:
    • Clear modeling of “this OR that” (sum types) and “this AND that” (product types).
    • Compiler‑enforced exhaustiveness checks when matching on variants.
    • Reduced boilerplate and clearer error handling (e.g., Result/Option vs T | null).
  • Others argue ADTs are not a “basic human mental model” and that this is overstated; people don’t naturally think in formal logic, even if AND/OR are useful abstractions.

Sum types vs unions and nullable types

  • Debate over whether TypeScript-style unions are equivalent to sum types:
    • Pro‑difference side: true sum types are disjoint; overlapping cases (e.g., same variant type on both sides) remain distinguishable, aiding composition and error/success separation.
    • Skeptical side: some see disjointness as an overcomplication; propose workarounds like extra variants (Missing) or Option<null>.
  • Several examples show how T | null or unions without explicit tags can become ambiguous or non‑composable.

Syntax sugar, power, and human factors

  • One group treats nested pattern matching as “just syntax sugar” over simpler constructs; from a PL-design lens, it doesn’t add expressiveness.
  • Others counter that “syntax sugar is power” socially:
    • What’s easy and pleasant becomes idiomatic; what’s painful is avoided even if theoretically possible.
    • Comparisons to structured control flow vs goto: constraints and readability matter more than raw power.

ADTs vs OOP / traits

  • ADTs (enums/sum types) are described as closed sets of variants but open to new functions; traits/interfaces are the dual (open to new implementations, closed to new methods).
  • This is linked to the “expression problem” and tradeoffs between adding new variants vs new operations.
  • Some see class hierarchies and sealed class patterns as ad‑hoc tagged unions with more ceremony.

Datatype99 and C macro approach

  • Datatype99 is viewed as impressive macro “wizardry” that layers ADT-like syntax and pattern matching over C tagged unions.
  • Supporters say:
    • C’s union+enum pattern already approximates tagged unions; macros remove boilerplate and provide better ergonomics.
    • C99 is a stable, widely available target; adding ADT sugar here is pragmatic.
  • Critics warn:
    • Heavy preprocessor use is hard to debug and maintain; past “clever” macro codebases are described as nightmares.
    • Datatype99 has limitations: no named fields in patterns, positional matching only, no nested struct/union patterns, and caveats around break/continue inside macro‑generated constructs.
    • Some see the design as not truly type‑safe and prefer languages with native ADTs (Rust, Swift, Zig, Nim, modern Java, etc.).

Language ecosystem and adoption

  • Multiple examples show ADTs and pattern matching spreading into mainstream imperative languages (Rust, Swift, Kotlin, Scala, Typescript, Dart via sealed classes, Java 21’s sealed classes + pattern matching).
  • However, long‑lived ecosystems (especially Java and C) move slowly; many codebases remain on old versions or in C, making macro‑based or library approaches attractive stopgaps despite their flaws.