> Am 16.05.2016 um 21:29 schrieb Thorsten Seitz via swift-evolution > <swift-evolution@swift.org>: > > >>> 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 >> >> `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 >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution