> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
> <[email protected]>:
> 
> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> <[email protected]>:
>> 
>> 
>> on Wed Jun 08 2016, Jordan Rose <[email protected]> wrote:
>> 
>>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>> <[email protected]> wrote:
>>>> 
>>>> 
>>>> on Wed Jun 08 2016, Thorsten Seitz
>>> 
>>>> <[email protected]
>>>> <mailto:[email protected]>>
>>>> wrote:
>>>> 
>>>>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>>>> to read up again what the reasons are for that behavior).
>>>> 
>>>> Yes, but in the case of the issue we're discussing, the choices are:
>>>> 
>>>> 1. Omit from the existential's API any protocol requirements that depend
>>>> on Self or associated types, in which case it *can't* conform to
>>>> itself because it doesn't fulfill the requirements.
>>>> 
>>>> 2. Erase type relationships and trap at runtime when they don't line up.
>>>> 
>>>> Matthew has been arguing against #2, but you can't “fix the bug” without
>>>> it.
>>> 
>>> #1 has been my preference for a while as well, at least as a starting
>>> point. 
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any<Protocols...>, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe this
>> is not so bad.
> 
> I think the problem is more that Any<Collection> does not conform to a 
> specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a generic 
> parameter `T: Collection` denotes a specific (though unknown) member of that 
> type family and `Any<Collection>` denotes the type family again, so there is 
> really no point in writing Any<Collection> IMO. 
> The type family cannot conform to T because T is just one fixed member of it.
> It conforms to itself, though, as I can write
> let c1: Any<Collection> = …
> let c2: Any<Collection> = c1
> 
> That’s why I think that we could just drop Any<Collection> and simply write 
> Collection.


Let me expand that a bit:

Actually all this talk about existentials vs. generics or protocols vs. classes 
has had me confused somewhat and I think there are still some misconceptions 
present on this list sometimes, so I’ll try to clear them up:

(1) misconception: protocols with associated types are somehow very different 
from generics

I don’t think they are and I will explain why. The only difference is the way 
the type parameters are bound: generics use explicit parameter lists whereas 
protocols use inheritance. That has some advantages (think long parameter lists 
of generics) and some disadvantages.
These ways are dual in a notation sense: generic types have to have all 
parameters bound whereas protocols cannot bind any of them.
The „existential“ notation `Any<>` being discussed on this list is nothing more 
than adding the ability to protocols to bind the parameters to be used just 
like Java’s wildcards are adding the opposite feature to generics, namely not 
having to bind all parameters.

Essentially `Any<Collection>` in Swift is just the same as `Collection<?>` in 
Java (assuming for comparability’s sake that Swift’s Collection had no 
additional associated types; otherwise I would just have to introduce a 
Collection<Element, Index> in Java).

Likewise `Any<Collection where .Element: Number>` is just the same as 
`Collection<? extends Number>` in Java.

And just like Collection<?> does not conform to a type parameter `T extends 
Collection<?>` because Collection<?> is the type `forall E. Collection<E>` 
whereas `T extends Collection<?>` is the type `T. Collection<T>` for a given T.

In essence protocols with associated types are like generics with wildcards.

Coming back to the questions whether (a) allowing existentials to be used as 
types is useful and (b) whether sacrificing type safety would somehow be 
necessary for that, I think we can safely answer
(a) yes, it *is* useful to be able to use existentials like Any<Collection> as 
types, because wildcards are quite often needed and very useful in Java (they 
haven’t been added without a reason)
(b) no, sacrificing type safety does not make sense, as the experience with 
Java’s wildcards shows that this is not needed. Especially if something like 
path dependent types is used like proposed and some notation to open an 
existential’s type is added, which is both something that Java does not have. 


(2) misconception: POP is different from OOP

It is not. Protocols are just interfaces using subtyping like OOP has always 
done. They just use associated types instead of explicit type parameters for 
generics (see above). The more important distinction of Swift is emphasizing 
value types and making mutation safely available by enforcing copy semantics 
for value types.
But protocols are not really different from interfaces in Java. I would have 
preferred a unified model using just classes with real multiple inheritance 
like Eiffel has and value types just being a part of that similar to Eiffel’s 
`expanded` classes. But that ship has probably sailed a long time ago :-/
So be it. But at least there should be no reasons for POP vs OOP wars ;-)
(I’d like to add that I liked Dave’s talks at last WWDC very much, it’s just 
that I don’t think that POP is something new or different.)


-Thorsten







_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to