> Am 15.05.2016 um 10:57 schrieb Adrian Zubarev via swift-evolution 
> <swift-evolution@swift.org>:
> 
>> I think an important point is that `all<>` should NOT be restricted to 
>> having only one reference or value type!
> 
> This is a little problematic and I’m not a compiler expert so from my 
> perspective I could allow that but in a different way you see it (I’ll 
> explain below).
> 
>> Ceylon does not have any restrictions like that. You can form the type 
>> intersection of String and Integer for example, which are both classes in 
>> Ceylon and because Ceylon like Swift only knows single inheritance between 
>> classes, the result is simply `Nothing` (the bottom type which has no 
>> elements). So there is no need to forbid this explicitly, because the types 
>> work out just fine.
> 
> If I remember correctly someone said that `Ceylon` does use `all` and `any` 
> for its Optional?! We can’t to do this in Swift as far as I know our 
> playground.
> 
> We don’t have `Nothing` in Swift. The counterpart would be `Optional` but 
> such a type is made explicit by `?` symbol like `Type? == Optional<Type>` and 
> the only equivalent to `Nothing` would be `nil`.
> 
`Nothing` is the bottom type, i.e. the intersection of all types. It has no 
members.
`Nothing` has nothing to do with optionals. Optionals in Ceylon are type unions 
with the type `Null` which has a single member called `null` (= Swift’s nil).

Maybe this proposal should start with forbidding creating `All<>` expressions 
which would evaluate to `Nothing` and a later proposal could introduce the 
bottom type.

> That been said, if `All<>` would always intersect (what I haven’t proposed 
> here at all) we can’t replace `protocol<>` with `All<>` because if we look at 
> two distinct protocols `A` and `B` and try to merge them into a type `All<A, 
> B>` would resolve in `implicit nil` where the old fashion way is not 
> `protocol<A, B>`.
> 
I don’t know from where you got `implicit nil`. Seems I was a bit unclear :-)
All<A, B> is the intersection type of A and B, i.e. a type which conforms to A 
*and* B.
Only for cases where A and B are *classes* which do *not* share an inheritance 
relation the result of All<A, B> is `Nothing` (the empty bottom type). This is 
a special case. The reason is that because of single inheritance it is 
impossible to define a subtype of two different class hierarchies.
If A and B are structs the result of All<A, B> is `Nothing` as well, because 
structs are not subtypeable at all. Note that All<StructA, StructA> will just 
be StructA, though.
If at least one of A and B is a protocol it is always possible to define a type 
that conforms to A and B.

> By the way, really an `implicit nil`? This is not a great idea if you ask me. 
> 
> You may have a look at this document: 
> https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md 
> <https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md>
> `All<String, Int> == implicit nil` (your way) while it probably `All<String, 
> Int>? == nil` would serve your wished behavior, but again I wasn’t proposing 
> on solving this issue here. I’d like to solve this problem 
> https://openradar.appspot.com/20990743 
> <https://openradar.appspot.com/20990743> and open the door for `AnyStruct`, 
> `AnyEnum`, `AnyValue` (maybe `AnyTuple` someday). This is what your hint for 
> `Any<>` combined with my `All<>` might create.
> 
> If we allow multiple reference and value types for `All<>` this will only 
> work with subtypeable types, because as I already described above 
> `All<StructA, StructB>` can’t be merged.
> 
Yes, as long as subtyping structs is not possible in Swift All<StructA, 
StructB> would be `Nothing` (again: this is not the type of `nil`).

> A scenario that will work might look like this:
> 
> class A {}     class B: A {}     class C: B {}
> 
> `All<B, C, A>` from the given types and my understanding the compile could 
> and should infer `C` from here (not `B` compared to your example below).
> 
> 

Oops, sorry, you are right. I again made the error of confusing intersection 
types (all<>) with union types (any<>). Grrr. I’m used to the type operators, 
that’s my only excuse…

> To sum up a little we would have these facts:
> 
> - for subtypeable types the compile will search the highest type from the 
> inheritance path and ignore all other lower base types (for `All<A, B>` the 
> compile would infer `B == All<B> == All<B, A>`)
> 
With `highest` you mean `most specialized`, right? (for me that’s the lowest 
type :-)

> - the oder of types should not matter because of the previous fact
> 
Exactly.

> That been said do we still need the whole inheritance branch inside of 
> `All<>`? I don’t think so.
> 
Right, the whole branch is definitely not needed.

> Furthermore if we definitely should ignore order of `Types` inside the angle 
> brackets like `All<A, B> == All<B, A>`, because it makes sense from the 
> context of creating a `Type` that is constrained to `A` AND `B` where AND is 
> commutative. I didn’t thought of at first glance, but thanks to your examples 
> it’s clear to me know.
> 
Yes, `all<>` should be commutative.

> ———
> 
> If one would want to store or pass `A` from `class A: ClassB, ProtocolC` in 
> some generic context and we don’t allow a second reference for `All<>` the 
> following sample won’t work (generalized `class` is assumed):
> 
> `func <T: class>(value: All<T, ClassB, ProtocolC>)` but you can workaround 
> here `func <T: ClassB>(value: All<T, ProtocolC>)` which can already be done 
> `func <T: ClassB where T: ProtocolC>(value: T)`
> 
> The only problem that rises up here is that we can’t store that value inside 
> a non-generic `Type` with both distinct `ClassB` and `ProtocolC` constraints 
> merged together. As you might guess `ProtocolC` is applied onto `A` but not 
> on `B` where `All<ClassB, ProtocolC>` will create a whole new type for us 
> (https://openradar.appspot.com/20990743 
> <https://openradar.appspot.com/20990743>).
> 
>> Furthermore you can form type intersections between reference types which 
>> inherit from each other. The resulting intersection type is valid and is 
>> just equal to the more specific type. And of course you can form type 
>> intersections of a reference or value type with itself (i.e. all<SomeClass, 
>> SomeClass>).
> 
>> Why should that be useful you may ask?
>> 
>> This generality is important when using intersection types with generics: 
>> let’s consider the type of a function forming the intersection of two sets 
>> with different element types:
>> 
>> func union<T, U>(a: Set<T>, b: Set<U>) -> Set<all<T, U>> { … }
>> 
>> 
>> Requiring all<T,U> to have at most one reference or value type (which must 
>> be at first position) would impose some unnecessary restrictions:
>> 
>> Given the following:
>> 
>> protocol Named {}
>> class Person : Named {}
>> class Employee : Person {}
>> 
>> let people: Set<Person>
>> let otherPeople: Set<Person>
>> let employees: Set<Employee>
>> let namedOnes: Set<Named>
>> 
>> // unnecessary restriction:
>> let x1 = union(namedOnes, people)  // not allowed, because result type 
>> contains all<Named, Person> 
> 
>> // the restriction would require us to write:
>> let x2 = union(people, namedOnes)  // ok, result type would be 
>> Set<all<Person, Named>> which would be simplified by the compiler to 
>> Set<Named>

Correction: Set<all<Person, Named>> = Set<Person & Named> = Set<Person>

>> (Ceylon does this!)
> 
>> // unnecessary restriction:
>> let x3 = union(people, employees)   // not allowed, because result type 
>> would contain all<Person, Employee> with two reference types
> 
>> // unnecessary restriction
>> let x4 = union(people, otherPeople)   // not allowed, because result type 
>> contains all<Person, Person> with two reference types
> 
>> 
>> IMO these should all be allowed (and are possible in Ceylon). 
>> The result type of x1 would be Set<all<Named, Person>> which would be 
>> simplified by the compiler to Set<Named>.

Correction: Set<Person>

>> The result type of x2 would be Set<all<Person, Named>> which would be 
>> simplified by the compiler to Set<Named>.

Correction: again Set<Person>

>> The result type of x3 would be Set<all<Person, Employee>> which would be 
>> simplified by the compiler to Set<Employee>.
>> The result type of x4 would be Set<all<Person, Person>> which would be 
>> simplified by the compiler to Set<Person>.

These two are correct, at least…

Sorry again for the confusion!

-Thorsten


>> 
>> -Thorsten
> 
> Pleas rethink your example here, `Intersection<>` might be a proposal of its 
> own (there are some problems with `Nothing` I described above).
> 
> ——— 
> 
> `Any<>` will pick only one type from its angle brackets. The types must be 
> distinct to each other, but `Any<>` is a whole other proposal which has its 
> own problems like:
> 
> protocol A {}    protocol B {}     class C: A, B {}
> 
> func foo(value: Any<A, B>) {
>      // if else if won’t handle `value` correctly if it’s `C`
> }
> 
> Is such a thing intended? I guess `Any<>` should just proceed when the first 
> match is found at compile time and it’s up to the developer to handle `value` 
> correctly.
> 
> In different thread I just answered my vision for `All<>` and future `Any<>`:
> 
> There are two future directions in my proposal: 
>        (1) `Any<>` which takes only one type from the angle brackets: 
> `Any<String, Int>` or `String | Int`
>        (2) if we already have a generalized `class` keyword, so why we don’t 
> get `struct` and `enum` as well?
> 
> With this we can create a typealias for `AnyValue` like this (at least for 
> generalized extendable types): 
>        `typealias AnyStruct = All<struct>`
>        `typealias AnyEnum = All<enum>`
>        `typealias AnyValue = Any<All<struct>, All<enum>>`
>        `typealias AnyValue = AnyStruct | AnyEnum`
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to