[swift-evolution] [Completing Generics] Opening existentials

Jonathan Tang jonathan.d.tang at gmail.com
Thu Mar 10 03:52:50 CST 2016


 On Wed, Mar 2, 2016 at 5:22 PM, Douglas Gregor via swift-evolution <
swift-evolution at swift.org> wrote:

>
> *Opening existentials*
>
> Generalized existentials as described above will still have trouble with
> protocol requirements that involve Self or associated types in function
> parameters. For example, let’s try to use Equatable as an existential:
>
> protocol Equatable {
>   func ==(lhs: Self, rhs: Self) -> Bool
>   func !=(lhs: Self, rhs: Self) -> Bool
> }
>
> let e1: Equatable = …
> let e2: Equatable = …
> if e1 == e2 { … } *// error:* e1 and e2 don’t necessarily have the same
> dynamic type
>
>
> One explicit way to allow such operations in a type-safe manner is to
> introduce an “open existential” operation of some sort, which extracts and
> gives a name to the dynamic type stored inside an existential. For example:
>
>
>
> if let storedInE1 = e1 openas T {     // T is a the type of storedInE1, a
> copy of the value stored in e1
>
>   if let storedInE2 = e2 as? T {      // is e2 also a T?
>
>     if storedInE1 == storedInE2 { … } // okay: storedInT1 and storedInE2
> are both of type T, which we know is Equatable
>
>   }
>
> }
>
>
>
>
Any chance we could have the as? operator used for opening existentials
instead of introducing a new openas one?

My reasoning is that the usage for opening an existential is very similar
to the usage for downcasting to a subtype.  In both cases, the initial
variable may be one of a large number of possible values, and you are
conditionally testing for membership in a subset of those values.  With the
downcast, the subset is a subtype.  With the existential, the subset is a
single type in the type family.  Indeed, in many cases your "test for a
concrete type conforming to a protocol" became a "test for a dynamic type
in an existential" because you added an associated type or Self reference
to your protocol.  Syntactically, the rest of your program is identical.

I don't *think* there's any chance for ambiguity here: right now, you can't
even create a value of type Equatable (since it can only be used as a
generic constraint), so these are completely disjoint situations.

It'd also be neat if there was a standard library function for "if two
objects are the same type and both equatable, compare with ==.  Otherwise,
return false."  This seems to be by far the most common definition of
.equals in languages in languages that let you override it (Java, Python,
etc.)  Maybe as a default method on Equatable?

As a side note, will existentials mean that protocols can finally be useful
in Sets
<http://stackoverflow.com/questions/29278624/pure-swift-set-with-protocol-objects>?
Since Set requires that its element be Hashable yet adopting Hashable
requires that the protocol can only be used as a generic constraint, you
can't really put a bunch of objects all conforming to a protocol in a Set
and do anything useful with them.  This is a really common pattern for eg.
having a bunch of objects that all do something and wanting to apply all of
their effects.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160310/411ec0dc/attachment.html>


More information about the swift-evolution mailing list