[swift-evolution] Enhanced existential types proposal discussion

Dave Abrahams dabrahams at apple.com
Wed Jun 8 13:57:59 CDT 2016

on Sun Jun 05 2016, Douglas Gregor <swift-evolution at swift.org> wrote:

> Sent from my iPhone
>> On Jun 5, 2016, at 6:41 PM, Matthew Johnson <matthew at anandabits.com> wrote:
>> Sent from my iPad
>>> On Jun 5, 2016, at 6:20 PM, Douglas Gregor <dgregor at apple.com> wrote:
>>>> On May 18, 2016, at 12:35 AM, Austin Zheng <austinzheng at gmail.com> wrote:
>>>> I've put together a considerably more detailed draft proposal,
>>>> taking into account as much of Matthew's feedback as I could. You
>>>> can find it below:
>>>> https://github.com/austinzheng/swift-evolution/blob/az-existentials/proposals/XXXX-enhanced-existentials.md
>>>> Since there is no chance this will come up for review anytime
>>>> soon, I expect to make significant revisions to it over the next
>>>> month or so. Any feedback would be greatly appreciated.
>>> This is very much Swift 4 territory, but I can’t help myself… so…
>>> The actual feature description is spread out through this very long
>>> document, with user-facing ideas (e.g., using “anonymous associated
>>> types”) intermixed with deeper technical details (existential type
>>> equivalence), so it’s very daunting to read. Please bring the
>>> user-facing features to the front (“Proposed Solution”) with
>>> examples, and save the deeper technical details for “Detailed
>>> Design”. You want more readers to make it through the part that
>>> affects them.
>>> Shortcut 'dot' notation: If there is only one protocol with
>>> associated types specified in the requirements, and there are no
>>> nested Any<...> requirements with where clauses of their own, that
>>> protocol's name can be omitted from the whereclause constraints:
>>> // Okay
>>> // Would otherwise be Any< ~ where Collection.Element == Int>
>>> let a : Any<class, Collection, Any<Streamable, CustomStringConvertible> where .Element == Int>
>>> // Both Collection and OptionSetType have associated types.
>>> let b : Any<Collection, OptionSetType where .Element == Int>
>>> FWIW, I think “.Element == Int” should be the only syntax. In
>>> generic signatures, if you have two different protocols with
>>> same-named associated types, and a given type parameter (or
>>> associated type) conforms to both protocols, the associated types
>>> are (implicitly) made equivalent via an inferred same-type
>>> constraint. So there’s no reason to introduce the
>>> “Collection.Element == Int” syntax, because the “Collection” part
>>> is basically irrelevant.
>>> Once existentials have been suitably enhanced, there is a strong
>>> analogy between an existential and a generic signature with a
>>> single type parameter that you can’t name. An existential
>>> Any<Collection where .Element : Equatable> has most of the same
>>> characteristics as a generic something with the signature <T :
>>> Collection where T.Element : Equatable>. Specifically, the sections
>>> on “Existential type equivalence”, “Ordering”, “Real types to
>>> anonymous associated types”, “Anonymous associated types to real
>>> types”. could be reduced to a few small, simple examples and a
>>> mention of the analogous behavior of generics. It will be far
>>> easier to explain this way, and readers don’t need to get immersed
>>> in the details. Where there are differences vs. generics, that’s
>>> important to point out.
>>> “Associated typealias rewriting”: this also falls out of the equivalence with generics + SE-0092.
>>> “Associated types and member exposure”: you don’t make the point
>>> that it only makes sense to refer to the associated types of a let
>>> constant; a var could change its type dynamically, which would
>>> invalidate the typing rules. Did you consider just using
>>> “x.dynamicType” in the type grammar for this? It’s more general, in
>>> that you can refer to associated types but also talk about the
>>> dynamic type of “x” itself, e.g.,
>>> 	let x: Equatable = …
>>> 	let y: Equatable = …
>>> 	if let yAsX = y as? x.dynamicType { … x == yAsX … }
>>> which is (almost?) as powerful as a general “open” expression.
>>> I’m not a fan of the “anonymous associated types” terminology:
>>> these are associated types of a type of some runtime-defined
>>> value. The only thing “anonymous” about them is that it’s harder to
>>> spell the base type; otherwise, they’re just like associated types
>>> of a generic type parameter. Again, the generics analogy is strong
>>> here.
>>> FWIW, I don’t think we’ll ever need “opening existentials” with
>>> what you’ve described here. Also, remember that a method of a
>>> protocol extension essentially opens “Self”, so we already have one
>>> way to open an existential (and that’s probably enough).
>>> I was a little surprised you didn’t point out that AnyObject could become
>>> 	typealias AnyObject = Any<class>
>>> or give the nice “AnyCollection” syntax:
>>> 	typealias AnyCollection<T> = Any<Collection where .Element == T>
>>> the latter of which is fairly important, because it gives nice
>>> syntactic sure to one of the most highly-requested features
>>> [*]. I’d suggest having that example very, very early.
>>> 	- Doug
>>> [*] That generally comes in as “Swift should have parameterized protocols…”
>> Great feedback here Doug.
>> FWIW, we also occasionally get "Swift should have parameterized
>> protocols" in the context of multiple conformances by the same
>> concrete type (as in things like ConvertibleTo<T> protocol).
> I know. From the bugs I've seen it's at least 10x as many requests for
> "any collection of some element type" as for any actually reason why
> one would need parameterize a protocols.

That does, however, speak for the idea that a concise and obvious syntax
should be supported for that use-case.

Personally, it doesn't seem ridiculous to me that some associated types
might usefully be written as type parameters on a protocol.  As
Collection shows, not all associated types are equally important.
Approximately nobody wants the existential “Collection where Index ==


More information about the swift-evolution mailing list