For those thinking of this as a special case of an object variant, it is .. here's an equivalent "desugaring" syntax: type ExtraEither[A, B] = object field: int case _: _ of Le: _: tuple[le: A] of Ri: _: tuple[ri: B] Run
It is roughly equivalent, in the above enum notation, to: ExtraEither[A, B] = enum of Le: tuple[field: int, le: A] of Ri: tuple[field: int, ri: B] Run This highlights the important properties and differences in how the sum type is special over the object variant, similar to how a scalar type like int is special compared to an `array[1, int]`: * it has only one discriminator / tag * that tag (and potentially its type) is anonymous and/or implicit * each branch has one tuple of "contents" which may be empty The above two points are important for thinking about the tag type in terms of the ergonomics, assumptions and operations that it enables, compared to an object variant (just like array-of-1 is a convenient special case in the language): * We can construct an instance with incomplete knowledge about the "other" branches - for `Either[A, B]`, I can construct the Either knowing only one of A and B - from the example, `Either.Le(42, false)` must be implicitly convertible to `Either(bool, _)` with the B left unspecified at the instantiation point - this is an important feature! * We can construct pattern matchers that are exhaustive and don't know the name or type of the tag field * These pattern matches can assume that each branch is fully defined and can offer syntax centering on the fact that the branch "members" are contained in a single tuple-like construct In the example, I threw in a little conveniece, ie the ability to add "global" fields that apply to all branches - these do not interfere with the above points about how the enum type is more specialized than an object variant. Thinking about it this way, we could potentially integrate it better with the language too. Nim for example allows constructing arrays where the "length" is a type, ie `array[bool, int]` \- this is in part why I don't feel the `enum` proposal fully embraces and integrates with "the rest" \- I'd like to be able to create sum types whose branches are `bool` because that is an important player / special case in this field: it limits the sum type even further by saying there are exactly two branches (which in generic / macro code could be treated special). One can also easily imagine a sum type over a `static int` with that many branches, each identified positionally, without losing the above 3 properties that makes the sum type "special".