It feels like there is some overlap in use cases for union types and enums, and I’m wondering whether there already has evolved some pragmatic, hands-on rules of thumb for deciding which one to use for a given scenario…? One example is the use of union types representing Lisp types in this discussion. For another one, I’ve been looking into tag URIs and I’d be leaning towards representing the date
component as
type DateSpec = Year | YearMonth | LocalDate
To my understanding, union types (in concert with other language features) can be used to emulate most aspects enums, except for inheritance and GADT aspects. A union type over some “wrapper” types like opaque types or single field case classes would make for a tagged union type. Using full-fledged case classes as product type constituents would give me the full ADT “shape”. Type classes and extensions work fine with union types, as well.
It feels like union types, as the more lightweight approach, might be the default. But then I wonder whether there’s a “boiling frogs” bias where one keeps throwing other language features at a union type beyond the point where an enum would’ve been more practical and concise.
A friend suggested that this resembles the choice between (anonymous/named) tuples and proper case classes, but I’m not 100% sure this nicely captures the essence, as the gap between runtime characteristics and typing effort is closer in this case than for union types vs enums.
Certainly not a crucial question, just wondering whether anybody has given this some thought already.