[swift-evolution] Enhanced existential types proposal discussion
Adrian Zubarev
adrian.zubarev at devandartist.com
Wed May 18 15:57:26 CDT 2016
So without any initial constraints how would one use this generic function??
extension UIButton: ProtocolA {}
let button = UIButton()
let shadowedButton: ProtocolA = UIButton()
// creates a set of a least one element if the generic type could be inferred
func unionIfPossible<T, U>(_ a: T, _ b: U) -> Set<Any<T, U>>? { /* merge somehow if possible */ }
You would not be able to form Any<T, U> here because T and U are generic arguments unknown. We don’t accept those, only `class`, specific classes, and specific protocols (and recursively, other Any).
Why would Any<…> does not work with the generic system here? To me it makes no sense, I as a developer would assume I can use a generic Type anywhere a type can be used (protocols and their associated types are a special case).
I would assume that:
func foo<T: UIView>(value: Any<T, SomeProtocol>)
should be equal to (without the need of generics):
func foo(value: Any<UIView, SomeProtocol>)
// this should be valid because the compiler will assume Any<UIView, ProtocolA> where T == UIView and U == ProtocolA
let merged_1: Set<Any<UIView, ProtocolA>> = unionIfPossible( /* UIView subtype */ button, /* ProtocolA */ shadowedButton)
// this won’t be possible because of the restriction
let merged_2: Set<Any<UIView, ProtocolA>> = unionIfPossible(shadowedButton, button)
Any<UIView, ProtocolA> != Any<ProtocolA, UIView> isn’t right. Sure it may feel right for readability but the types should be equal.
"Can be any class type that is a UIView or a subclass of UIView, that also conforms to ProtocolA.“ == "Type that conforms to ProtocolA and that is a UIView or a subclass of UIView.“
This is also a nesting problem where you will be forced to choose the right place inside the angle brackets where to add a nested `Any<…>`.
class A: ClassB, ProtocolA {}
Any<A, Any<ClassB, ProtocolA>> == A != Any<Any<ClassB, ProtocolA>, A> == Any<ClassB, ProtocolA, A> which should be reorder by the compiler and inferred as A
`Any<Any<ClassB, ProtocolA>, A>` is not allowed because if a class is provided it must come first.
`Any<ClassB, ProtocolA, A>` is not allowed because it contains more than one class.
Not true, take a look at the nested section of the proposal again.
We discussed that this is valid:
// Allowed, but pointless.
// Identical to Any<ProtocolA, ProtocolB>
let b : Any<Any<ProtocolA, ProtocolB>>
This implies that also this would be valid:
Any<Any<ClassA, ProtocolA>> inferred as Any<ClassA, ProtocolA>
There is another example:
// Can be any type that is a UITableView conforming to ProtocolA.
// UITableView is the most specific class, and it is a subclass of the other
// two classes.
let a : Any<UIScrollView, Any<UITableView, Any<UIView, ProtocolA>>>
Which followed by the mentioned rule can als be:
Any<UIScrollView, UITableView, Any<UIView, ProtocolA>> or
Any<UIScrollView, UITableView, UIView, ProtocolA>
This would force us to allow multiple classes inside Any<…> if there is a inheritance relationship between them.
And because this is a inheritance relationship it can be simplified to:
Any<UITableView, ProtocolA> which is valid.
And by the way since the order in your proposal would matter, this example won’t work at all, because its not:
Any<UITableView, Any<UIScrollView, Any<UIView, ProtocolA>>>
In my proposal I explicitly banned multiple reference types and inheritance branches like this. I would need to simplify that type to Any<UITableView, ProtocolA> by myself.
Ingeneral this is a good idea, but it makes nesting (with typealiases) almost impossible, when there are some relationship like in the above example.
--
Adrian Zubarev
Sent with Airmail
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160518/dad5bc89/attachment.html>
More information about the swift-evolution
mailing list