Sum-tuple proposal rough draft

Sum-tuple syntax: (< item1 ; item2 ; ... >)

  • items are like in current tuples, now called product tuples: a type name, possibly preceded by a identifier label and colon.

  • A specific case can be assigned to by an assignment to the corresponding field.

      var x: (< number: Int; Double >)
    
      //...
    
      x.number = 5
      x.1 = -7.0e5
    
  • Use a switch to read from a sum-tuple

      class MyType {}
      class MyType2: MyType, Collection { /*...*/ }
    
      let y: (< Int ; Double ; MyType2 ; array: [Int] ; anotherDouble: Double >) = MyFunction(6)
      switch y {
      case .0:
          print("I got an Int")
      case .1(let d):
          print("I got a Double", d)
      case is Double:
          // This would have caught .1 too if the previous case wasn't there.
          print("This will catch 'anotherDouble'")
      case is MyType:
          print("This will catch the `MyType2` member")
      case c as Collection:
          print("This will only catch the `array`, since the previous case caught the only other possibility")
      }
    

    If a case is for a member that itself is a sum type, then a case can cascade to the inner value.

      enum MyType3 { mercury, venus, earth, mars }
    
      let z: (< Int ; MyType3 >) = MyFunction2("whatever")
      switch z {
      case .0(let i):  //...
      case .1.venus:  //...
      default:  //...
      }
    
  • To initialize a sum-tuple, we need a new syntax, using in:

      let aa: (< Int ; MyType3 ; anotherNumber: Int >) = 15 in .anotherNumber
    
  • The "(< >)" syntax should be used for product tuples too. The difference should be that product tuples use a comma to separate members, while sum tuples use a semicolon. Use a single semicolon between the bracketing to differentiate the empty product tuple from the empty sum tuple.

      typealias Void = (< >)
      typealias Never = (< ; >)
    
  • There is an ambiguity between sum tuples and new-style product tuples when there is exactly one member, but both should be implemented as the same as the type by itself, so there should be no problem in practice. We could require a trailing comma vs. semicolon if the type checker needs to know the difference.

      typealias SingleMemberProductTuple = (< Int, >)
      typealias SingleMemberSumTuple = (< Int ; >)
    

    To be consistent with the Void example, a single member tuple without a trailing punctuator should be assumed to be a product tuple. (Should there be a fix-it to add a ";" to a tuple's type if an instance is used in a switch?)

Any obvious holes I'm missing for the sum-tuple model/interface?

I did two other recent posts on the subject:

1 Like