> Am 16.05.2016 um 21:29 schrieb Thorsten Seitz via swift-evolution
> <[email protected]>:
>
>
>>> Am 15.05.2016 um 10:57 schrieb Adrian Zubarev via swift-evolution
>>> <[email protected]>:
>>>
>>> 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
>>
>> `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 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).
>>
>>> 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>> { … }
The text is correctly talking about intersection and the types are correct for
forming the intersection, but of course the function should be called
`intersection` as well!
This applies to its usage in the examples below...
Maybe we should use `union<>` and `intersection<>` :-)
-Thorsten
>>>
>>>
>>> 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
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution