[swift-evolution] Enhanced existential types proposal discussion

Douglas Gregor dgregor at apple.com
Thu Jun 9 11:06:23 CDT 2016


> On Jun 8, 2016, at 11:57 AM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> on Sun Jun 05 2016, Douglas Gregor <swift-evolution at swift.org <mailto: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>
>>>> 
>>>> // NOT ALLOWED
>>>> // 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 ==
> Int.”


I’ve toyed with some form of this idea before, and IIRC it was discussed on this list at one point, where some or all associate types move up to the “type parameter” position in the grammar, e.g.,

protocol Collection<Element> : Sequence<Element> {
  associatedtype Index
  associatedtype SubSequence
}

However, unless that is semantically a type parameter in the sense that one can have a single concrete type conform to Collection<A> and Collection<B> separately, I think it’s misleading to go this route, even if it does give us the clean “Collection<Int>” syntax.

	- Doug

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160609/3844a62d/attachment.html>


More information about the swift-evolution mailing list