[swift-evolution] Enhanced existential types proposal discussion

Matthew Johnson matthew at anandabits.com
Thu May 26 09:28:55 CDT 2016


> On May 26, 2016, at 8:51 AM, Jan E. Schotsman via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> On May 26, 2016, at 3:44 PM, Austin Zheng wrote:
> 
>> The inimitable Joe Groff provided me with an outline as to how the design
>> could be improved. I've taken the liberty of rewriting parts of the
>> proposal to account for his advice.
> 
> Looks like great progress!
> 
> A few remarks:
> 
> 1.I don't see the need for AllOf. A nested existential also acts as a constraint bundle, so you would have to write
> 
> Any<ProtocolA, AllOf< ProtocolB, ProtocolC>>
> 
> for consistency.

I’ve been thinking about this as well, especially in the context of Brent’s idea to distinguish existentials from generic constraints.  My conclusion is that disallowing use of `Any` (or typealiases of `Any`) in generic constraints is an arbitrary restriction and introducing a new name `AllOf` for something that is structurally the same is unnecessary and potentially confusing.

I would like to see us eventually introduce a first class mechanism for abstracting constraints.  That mechanism would become the preferred mechanism for factoring constraints, used in both generics and existentials.  When we have that mechanism it might be reasonable to push people to use it rather than “existential constraints”.  Maybe this can even happen along side enhanced existentials in Swift 4.

> 
> In a "is subclass of" constraint the superclass also acts as a constraint bundle, in a sense.
> 
> 2.If openas never fails why do we need to use optional binding with it?

I assume you’re talking about this:

let e1: Equatable = ...
let e2: Equatable = ...

if let storedInE1 = e1 openas T {
  // is e2 also a T? 
  if let storedInE2 = e2 as? T {
    // okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
    if storedInE1 == storedInE2 { ... }
  }
}

That is a good question.  I imagine the purpose is to require a new scope to be introduced, inside which `T` is bound to the dynamic type of `e1` and `storedInE1` is bound to a value of that type.  I am not sure why we need a new scope for these bindings rather than allowing them to be in effect in the surrounding scope (this may have been discussed already).  If the new scope is necessary it might be worth elaborating on why.  Otherwise, it would be simper if we could just do this:

let e1: Equatable = ...
let e2: Equatable = ...

let storedInE1 = e1 openas T
// is e2 also a T? 
if let storedInE2 = e2 as? T {
  // okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
  if storedInE1 == storedInE2 { ... }
}


> 
> 3. You have a typo in the "where clause" section:  where Collection.Element == Streamable
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160526/66d20417/attachment.html>


More information about the swift-evolution mailing list