> On Jun 6, 2016, at 12:22 AM, Dave Abrahams <dabrah...@apple.com> wrote: > > > on Sun Jun 05 2016, Matthew Johnson <matthew-AT-anandabits.com > <http://matthew-at-anandabits.com/>> wrote: > >> Sent from my iPhone >> >>> On Jun 5, 2016, at 3:51 PM, Dave Abrahams via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> >>> >>>> on Wed May 25 2016, Matthew Johnson <swift-evolution@swift.org> wrote: >>>> >>>> Sent from my iPad >>>> >>>>> On May 25, 2016, at 12:10 PM, Jordan Rose via swift-evolution >>>>> <swift-evolution@swift.org> wrote: >>>>> >>>>> >>>>>>> On May 25, 2016, at 05:27, Brent Royal-Gordon via swift-evolution >>>>>>> <swift-evolution@swift.org> wrote: >>>>>>> >>>>>>> AFAIK an existential type is a type T with type parameters that >>>>>>> are still abstract (see for example >>>>>>> https://en.wikipedia.org/wiki/Type_system#Existential_types), >>>>>>> i.e. have not been assigned concrete values. >>>>>> >>>>>> My understanding is that, in Swift, the instance used to store >>>>>> something whose concrete type is unknown (i.e. is still abstract), >>>>>> but which is known to conform to some protocol, is called an >>>>>> "existential". Protocols with associated values cannot be packed >>>>>> into normal existentials because, even though we know that the >>>>>> concrete type conforms to some protocol, the associated types >>>>>> represent additional unknowns, and Swift cannot be sure how to >>>>>> translate uses of those unknown types into callable members. Hence, >>>>>> protocols with associated types are sometimes called >>>>>> "non-existential". >>>>>> >>>>>> If I am misusing the terminology in this area, please understand >>>>>> that that's what I mean when I use that word. >>>>> >>>>> We’re not consistent about it, but an “existential value” is a value >>>>> with protocol or protocol composition type. My mnemonic for this is >>>>> that all we know is that certain operations exist (unlike a generic >>>>> value, where we also have access to the type). John could explain it >>>>> more formally. We sometimes use “existentials” as a (noun) shorthand >>>>> for “existential value”. >>>>> >>>>> In the compiler source, all protocols and protocol compositions are >>>>> referred to as “existential types”, whether they have associated >>>>> types or not. Again, a protocol asserts the existence (and >>>>> semantics) of various operations, but nothing else about the >>>>> conforming type. (Except perhaps that it’s a class.) All protocols >>>>> are thus “existential types” whether or not the language supports >>>>> values having that type. >>>>> >>>>> It is incorrect to say that protocols with associated types (or >>>>> requirements involving Self) are “non-existential”. >>>> >>>> I haven't heard people using this term myself, but I imagine they >>>> probably mean "can't form an existential value with the protocol". >>>> There certainly appears to be a lot of confusion in the community with >>>> many not realizing that this is a temporary limitation of the >>>> implementation, not a necessary fact. >>> >>> As far as I know there is no known way to make protocols with Self >>> requirements usefully “existentiable,” or whatever you want to call it. >>> So unless I'm missing something, in this respect, the limitation is not >>> temporary at all. >> >> Take a look at the Equatable example in the opening existentials >> section of Doug's manifesto: >> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160229/011666.html > > Yes, note that I said *usefully* “existential.”
Fair enough. But note that I was only talking about the inability to form and open such an existential which appears likely to be a temporary limitation given the generics manifesto (of course things could change). > While we can of > course downcast in this way, you have to handle the failure case and > it's not like you can use this to make a heterogeneous Set<Hashable>. > AFAICT, this is not at all like what happens with associated types, > where Collection<Element: Int> has obvious uses. We can’t use this to form Set<Hashable> because existentials don’t conform to the protocol. I know there is complexity in implementing this and it is not possible to synthesize conformance of the existential for all protocols, but AFAIK it isn’t a settled point that we won’t try to improve the situation in some way. Maybe we can make progress here somehow. In the meantime, we can make a simple wrapper type to provide the required conformance and make a Set<HashableWrapper> that allows us to put Hashable into a Set. This isn’t ideal but it is a lot less boilerplate than is involved in manual type erasure today where you need to define a struct, base class, and wrapper class. I’d say that’s a win even if we’d like to do better in the future. struct HashableWrapper: Hashable { var value: Hashable public var hashValue: Int { return base.hashValue } } public func ==(lhs: HashableWrapper, res: HashableWrapper) -> Bool { if let lhsValue = lhs.value openas T { // T is a the type of lhsValue, a copy of the value stored in lhs if let rhsValue = rhs.value as? T { // is res also a T? // okay: lhsValue and rhsValue are both of type T, which we know is Equatable if lhsValue == rhsValue { return true } } } return false } (We could also do this with a generic Wrapper<T> and conditional conformance in an `extension Wrapper: Hashable where T == Hashable` if we don’t want a bunch of wrapper types laying around) -Matthew > > -- > -Dave
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution