ipso icon indicating copy to clipboard operation
ipso copied to clipboard

Enum variants

Open LightAndLight opened this issue 4 years ago • 1 comments

Variants currently use the syntax < C_0 : T_0 | C_1 : T_1 | ... | C_n : T_n >. This syntax is a little verbose for constructors that take no arguments, because "no arguments" is represented by the unit type. I'd prefer to write < C | D > instead of < C : () | D : () >, and f C instead of f (C ()).

Right now, C : forall a r. a -> < C : a | r >. I want to keep principle types where possible, so using the simpler syntax I require that C : forall r. < C | r >. If that's the case, then I need a new syntax for multi-argument constructors.

Candidates:

  • Tuple style - C(1, "hi") : forall r. < C(Int, String) | r > An advantage of this syntax is that tuples are currently not defined/implemented, and I'm leaning away from ever doing that. Choosing between "a curried function with anonymous arguments" and "an uncurried function with named arguments" seems like enough options.
  • Record style - C{ a = 1, b = "hi" } : forall r. < C{ a : Int, b : String } | r >

Non-candidates:

  • Tuple style with braces - C{1, "hi"} : forall r. < C{Int, String} | r > I reject this because it introduces inconsistency in the meaning of {}, which I am committed to treating as a record.

Potential problems:

  • Tuple and record style might be grammatically or "semantically" ambiguous. f a b c is a function call. C a b c gives a type error. f (a, b) is a function call (if I implement tuples). C (a, b) is a constructor. f {a, b} is a function call. C {a, b} is a constructor.

    Exploring this ambiguity:

    • before
      (\a b -> f Test { a, b }) : 
        (
          (x -> < Test : x | r >) ->
          { a : a, b : b } ->
          c
        ) -> 
        a ->
        b ->
        c
      
    • after
      (\f a b -> f Test { a, b }) : 
       (
         < Test{ a : a, b : b } | r > ->
         c
       ) -> 
       a ->
       b ->
       c
      
    • before
      (\a b -> Test { a, b }) : 
        a ->
        b ->
        < Test : { a : a, b : b } | r >
      
    • after
      (\a b -> Test { a, b }) : 
       a ->
       b ->
       < Test{ a : a, b : b } | r >
      
  • Constructors are no longer functions.

  • I probably can't reuse the Row kind between records and variants.

LightAndLight avatar May 25 '21 10:05 LightAndLight

I'm leaning towards tuple-style right now. Also, embedding: (\x -> < C(Int, String) | x >) : forall r. r -> < C(Int, String) | r >.

LightAndLight avatar May 26 '21 06:05 LightAndLight