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) orOption<null>.
- Several examples show how
T | nullor 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/continueinside 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.