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".

Reply via email to