[swift-evolution] Enhanced existential types proposal discussion

Austin Zheng austinzheng at gmail.com
Wed May 18 16:17:46 CDT 2016


I'm not sure what your objections actually are, but my responses are inline.

On Wed, May 18, 2016 at 1:57 PM, Adrian Zubarev via swift-evolution <
swift-evolution at swift.org> wrote:

> 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).
>

Because what existentials are trying to model and what generic type
parameters are trying to model are two different things. You already cannot
use arbitrary types within a Any<> existential as the proposal stands.

This doesn't currently work in Swift, and it shouldn't: "func foo<A, B>()
-> protocol<A, B>". There is no useful way to generically compose instances
of two protocol types at runtime to form an instance of a type that
conforms to both protocols, like there is a way to compose instances of two
types to form a tuple containing those types. Therefore, writing a generic
function to do this makes no sense.


> 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>
>

Yes, this is valid.


>
> 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.
>

Yes. As explained in the proposal, there is already a way to handle
resolving the single 'effective' class constraint. You can only
'explicitly' declare one class constraint, but you can pull in other class
constraints from nested existentials for the sake of making composition
easier. In the end it doesn't matter, because if the class constraints
don't form a valid inheritance hierarchy the compiler will complain, and if
they do the most specific type will be chosen.


>
> 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>>>
>

The order does *not* affect the semantic meaning of the existential. There
is a section in the proposal on how existentials are conceptually 'reduced'
from whatever form they take when the programmer types them in, please read
it. I am not proposing a macro system. The compiler does not do textual
replacement in order to flatten nested existential definitions.

This is also why it makes no sense to have a generic "Any<T, U>", because
such a type is identical to "Any<U, T>", which is not true for any other
generic type or aggregate type in Swift.


>
> 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
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160518/c1062cea/attachment.html>


More information about the swift-evolution mailing list