Generalised concrete-type existentials


(James Froggatt) #1

I'd also like to see this. I expect there would be plenty of support if this got to the proposal stage, but I think you've already got the discussion covered quite comprehensively.

I think the class existential proposal made sense for this stage of Swift evolution because there were known APIs which could be changed/improved by it's addition. Generalisation to value types, while obvious (and something which should have been part of the original proposal, IMHO), is a more additive change. Examples of existing APIs which could be improved could fetch this proposal some more active support, but I suspect there will be fewer than there were for classes.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <7D62143A-4103-4DAF-9239-2C1ED4BE1B4E@springsup.com>

Now that SE-0156 has been accepted, I’ve been thinking recently that it might be nice to extend this proposal with some kind of generalised “concrete-type existential”. As I see it, there are two parts to an existential like the one proposed here:

<concrete type> & <protocol conformances...>

For classes, the “concrete type” part of this relationship is flexible: the instance may be the exact class X, or some subclass of X, and in that case it may or may not conform to additional protocols. So that’s why this existential has value; because, say, “NSObject & Collection” may be satisfied for some subclasses of NSObject.

Value-types cannot have subtypes, so that part of the constraint is fixed. Likewise, until now, the set of protocol conformances for a concrete type was fixed. That is to say that “Array <T> & Equatable” would be a nonsense constraint, because Array<T> does not conform to Equatable and will never conform to Equatable.

But we have approached everything focussed on the idea that only flexibility in satisfying the concrete-type constraint matters. Now that we have conditional conformances, however, the protocol-conformance side of the equation also becomes interesting, even for value-types. The existential “Array<T> & Equatable” is no longer a nonsense constraint - it is a valid constraint which implies some underlying constraints on T. In this case the underlying constraints might be simple (T: Equatable), but in general for any protocol “SomeProtocol”, the conditional conformance requirements might be long and complex, or even completely unknown to us (e.g. if the Foo: SomeProtocol conformance is added retroactively by another module).

For example, I should be able to write:

func checkArray<T>(_ a: Array<T> & SomeProtocol) -> Bool {
// …
}

Without needing to be copy-paste the requirements which make Array conform to SomeProtocol, or even needing to know the specifics of those constraints at all.

The solution would be to extend SE-0156 to allow { <non-class concrete type> & <protocol conformances> } existentials.

- Karl

------------- End Message -------------