> On Jan 29, 2017, at 10:47 PM, Slava Pestov <[email protected]> wrote:
> 
> 
>> On Jan 29, 2017, at 2:05 PM, Matthew Johnson via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>>> 
>>> On Jan 29, 2017, at 3:52 PM, Xiaodi Wu <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> On Sun, Jan 29, 2017 at 3:35 PM, Matthew Johnson <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>>> On Jan 29, 2017, at 3:24 PM, Xiaodi Wu <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>> On Sun, Jan 29, 2017 at 3:11 PM, Matthew Johnson <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>>> On Jan 29, 2017, at 3:05 PM, Xiaodi Wu <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>> On Sun, Jan 29, 2017 at 2:40 PM, Matthew Johnson <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>>> On Jan 29, 2017, at 2:25 PM, Xiaodi Wu <[email protected] 
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>> On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson <[email protected] 
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>>> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu <[email protected] 
>>>>>>> <mailto:[email protected]>> wrote:
>>>>>>> 
>>>>>>> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson 
>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>> 
>>>>>>> 
>>>>>>> Sent from my iPad
>>>>>>> 
>>>>>>> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>> 
>>>>>>>> Cool. Another avenue of improvement here is relaxing the single-class 
>>>>>>>> spelling rule for the sake of composing typealiases.
>>>>>>>> 
>>>>>>>> As Matthew mentioned, if I have class Base and typealiases Foo = Base 
>>>>>>>> & Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & 
>>>>>>>> Bar.
>>>>>>>> 
>>>>>>>> It'd be nice to go one step further: given class Derived : Base, if I 
>>>>>>>> have typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & 
>>>>>>>> Protocol2, then it could be permitted to write Foo2 & Bar2, since 
>>>>>>>> there is effectively only one subclass requirement (Derived).
>>>>>>>> 
>>>>>>>> As I understand it, the rationale for allowing only one subclass 
>>>>>>>> requirement is that Swift supports only single inheritance. Thus, two 
>>>>>>>> disparate subclass requirements Base1 & Base2 would make your 
>>>>>>>> existential type essentially equivalent to Never. But Base1 & Base1 & 
>>>>>>>> Base1 is fine for the type system, the implementation burden (though 
>>>>>>>> greater) shouldn't be too awful, and you would measurably improve 
>>>>>>>> composition of typealiases.
>>>>>>> 
>>>>>>> Yes, this is what I was indicating in my post as well.
>>>>>>> 
>>>>>>> Are you suggesting that Base1 & Base2 compose to a type that is treated 
>>>>>>> identically to Never do you think it should be an immediate compiler 
>>>>>>> error?  I remember having some discussion about this last year and 
>>>>>>> think somebody came up with a very interesting example of where the 
>>>>>>> former might be useful.
>>>>>>> 
>>>>>>> Last year's discussion totally eludes me for some reason. But sure, if 
>>>>>>> deferring the error until runtime is actually useful then why not? In 
>>>>>>> the absence of an interesting use case, though, I think it'd be nice 
>>>>>>> for the compiler to warn you that Base1 & Base2 is not going to be what 
>>>>>>> you want.
>>>>>> 
>>>>>> Deferring to runtime isn’t what I mean.  If you try to actually *do* 
>>>>>> anything that requires an instance of `Base1 & Based` (which you almost 
>>>>>> always would) you would still get a compile time error.
>>>>>> 
>>>>>> I managed to dig up the example from last year’s thread and it is 
>>>>>> definitely a good one:
>>>>>> 
>>>>>> func intersection<T, U>(ts; Set<T>, us: Set<U>) -> Set<T & U>
>>>>>> 
>>>>>> The desire is that we are always able to produce a result set.  When T & 
>>>>>> U is uninhabitable it will simply be an empty set just like Set<Never> 
>>>>>> has a single value which is the empty set.
>>>>>> 
>>>>>> Currently, Set<Never> is impossible because Never is not Hashable :)
>>>>> 
>>>>> Ahh, good point.  I hadn’t tried it.  It can easily be made Hashable with 
>>>>> a simple extension though - this code compiles today:
>>>>> 
>>>>> extension Never: Hashable {
>>>>>     public var hashValue: Int { return 0 }
>>>>> }
>>>>> public func ==(lhs: Never, rhs: Never) -> Bool { return false }
>>>>> let s = Set<Never>()
>>>>> 
>>>>>> Since concrete types *can't* be used, this example seems like it'd be of 
>>>>>> little use currently. How widely useful would it be to have an 
>>>>>> intersection facility such as this when T != U even if that restriction 
>>>>>> were lifted, though? Seems like the only real useful thing you can do 
>>>>>> with generic Set<T & U> is based on the fact that it'd be Set<Hashable>. 
>>>>>> Other than those immediate thoughts, I'll have to think harder on this.
>>>>> 
>>>>> Sure, it’s possible that this is the only interesting example and may not 
>>>>> have enough value to be worthwhile.  But I found it interesting enough 
>>>>> that it stuck around in the back of my mind for 8 months! :) 
>>>>>  
>>>>> Hmm, it had not occurred to me: instantiating a Set<Hashable> is not 
>>>>> supported (and you can substitute for Hashable any protocol you want). 
>>>>> Thus, for any Set<T> and Set<U> that you can actually instantiate, unless 
>>>>> T and U are both classes and one inherits from the other (in which case 
>>>>> the generic `intersection<X>(a: Set<X>, b: Set<X>) -> Set<X>` already 
>>>>> suffices), Set<T & U> must be the empty set. This is not a very 
>>>>> interesting result.
>>>> 
>>>> Yes, but this is a limitation due to the fact the existentials for a 
>>>> protocol do not conform to the protocol.  In some cases the existential 
>>>> *cannot* conform to the protocol but in many cases (especially common 
>>>> cases) it *can*.  It just doesn’t today.  There is widespread desire to 
>>>> see this situation improve.
>>>> 
>>>> Sure, but when will be the day that existentials conform to their own 
>>>> protocol when they can do so, *and* we extend `&` to value types (probably 
>>>> not until they can express some sort of meaningful subtyping relationship 
>>>> to each other)?
>>> 
>>> I hope it isn’t *too* long before existentials conform to their own 
>>> protocol at least in simple cases - Swift 5 if it doesn’t make it into 
>>> Swift 4.
>>> 
>>> I will bet you two virtual alcoholic beverages that it won't happen before 
>>> Swift 7 or one that it won't happen before Swift 9.
>>>  
>>> I am suggesting this proposal be generalized such that it discusses 
>>> concrete subtype / supertype relationships rather than restricting it’s 
>>> scope to classes.  If that approach is adopted then `&` would allow value 
>>> types as soon as this proposal is implemented.
>>> 
>>> It seems arbitrary and unnecessary to restrict it to classes even if that 
>>> is where it would be most useful when it is first implemented.
>>> 
>>> One can naturally relax the rules in tandem with the design and 
>>> implementation of prerequisite features that make the more relaxed rules 
>>> useful. The point I'm trying to make is: there is currently no value of X 
>>> for which the following statement holds true--
>>> 
>>> "If only it weren't for the restriction against writing `Base1 & Base2`, 
>>> I'd be able to implement the interesting algorithm X."
>>> 
>>> So it seems reasonable to error on `Base1 & Base2`.
>> 
>> If you’re right about the timeline for existentials conforming to their 
>> protocols I would agree with you wholeheartedly.  I’m not sure why we have 
>> such different perspectives on when that might happen.  It has certainly 
>> received plenty of demand from the community and caused some degree of 
>> confusion, usually in relatively simple cases (since we only have relatively 
>> simple existentials today).
> 
> Here are a couple of e-mails I sent recently explaining why self-conforming 
> existentials are tricky. Someone with a deep understanding of the compiler 
> needs to put some thought into how an implementation could work…
> 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160815/026349.html
>  
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160815/026349.html>
> https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161226/004292.html
>  
> <https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161226/004292.html>
Thanks for the links, I hadn’t seen these previously.  For some reason I 
thought the implementation complexity was focused on protocols with Self and 
associated type requirements and so basic support might be easier to implement 
as a first step.

> 
>> 
>>> 
>>>> 
>>>> At that point, I'd advocate for using compiler magic to make uninhabited 
>>>> types like Never a subtype of all types conforming to all protocols. Then, 
>>>> we could actually write Set<Never> without having to implement conformance 
>>>> to Hashable by writing a bogus `==` function. And we could replace 
>>>> EmptyCollection with Collection<Never> and simplify the standard library 
>>>> API surface that way (since Array<Never>() would then be a value of type 
>>>> Array<T>, etc.). And, your demonstrated use case would become interesting. 
>>>> Since there is a pretty good chance that you and I won't be alive by then, 
>>>> I'm happy to punt on the ideation process for this :)
>>>> 
>>>>> 
>>>>> It generalizes easily to any cases where you have a generic type that is 
>>>>> useful despite not necessarily having access to instances of the 
>>>>> parameterized type.
>>>>> 
>>>>> If we allow this, I *think* all uninhabitable types could be unified 
>>>>> semantically by making `Never` a protocol and giving them implicit 
>>>>> conformance.
>>>>> 
>>>>>> 
>>>>>> This example points even more strongly in the direction of allowing 
>>>>>> *any* concrete type to be used, not just classes - even today we could 
>>>>>> produce uninhabitable existentials like this using value types.
>>>>>> 
>>>>>> Here’s the link to the thread: 
>>>>>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/019463.html
>>>>>>  
>>>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/019463.html>
>>>>>>> 
>>>>>>> 
>>>>>>>> On Sun, Jan 29, 2017 at 12:41 Austin Zheng <[email protected] 
>>>>>>>> <mailto:[email protected]>> wrote:
>>>>>>>> The "class comes first" requirement made more sense when the proposed 
>>>>>>>> syntax was still "Any<T, U, V>", intentionally mirroring how the 
>>>>>>>> superclass and conformances are declared on a class declaration (the 
>>>>>>>> archives contain more detailed arguments, both pro and con). Now that 
>>>>>>>> the syntax is "T & U & V", I agree that privileging the class 
>>>>>>>> requirement is counterintuitive and probably unhelpful.
>>>>>>>> 
>>>>>>>> Austin
>>>>>>>> 
>>>>>>>> > On Jan 29, 2017, at 10:37 AM, Matt Whiteside via swift-evolution 
>>>>>>>> > <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>> >
>>>>>>>> > Thanks for writing this proposal David.
>>>>>>>> >
>>>>>>>> >> On Jan 29, 2017, at 10:13, Xiaodi Wu via swift-evolution 
>>>>>>>> >> <[email protected] <mailto:[email protected]>> 
>>>>>>>> >> wrote:
>>>>>>>> >>
>>>>>>>> >> As Matthew mentioned, the rules can certainly later be relaxed, but 
>>>>>>>> >> given that this proposal has the compiler generating fix-its for 
>>>>>>>> >> subclasses in second position, is there a reason other than 
>>>>>>>> >> stylistic for demanding MyClass & MyProtocol instead of MyProtocol 
>>>>>>>> >> & MyClass?
>>>>>>>> >>
>>>>>>>> >> From a naive perspective, it seems that if the compiler understands 
>>>>>>>> >> my meaning perfectly, it should just accept that spelling rather 
>>>>>>>> >> than complain.
>>>>>>>> >
>>>>>>>> > I had that thought too.  Since ‘and’ is a symmetric operation, 
>>>>>>>> > requiring the class to be in the first position seems 
>>>>>>>> > counter-intuitive.
>>>>>>>> >
>>>>>>>> > -Matt
>>>>>>>> >
>>>>>>>> > _______________________________________________
>>>>>>>> > swift-evolution mailing list
>>>>>>>> > [email protected] <mailto:[email protected]>
>>>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>> 
>>>>>>>> _______________________________________________
>>>>>>>> swift-evolution mailing list
>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> 
>>> 
>>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>

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

Reply via email to