<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 2, 2016, at 5:22 PM, Douglas Gregor via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div></div><div class=""><br class=""></div><div class=""><b class=""><font size="4" class="">Removing unnecessary restrictions</font></b></div><div class=""><br class=""></div><div class=""><span style="font-size: 14px;" class=""><i class="">Concrete same-type requirements</i><br class=""></span></div><div class=""><br class=""></div><div class=""><div class="">Currently, a constrained extension cannot use a same-type constraint to make a type parameter equivalent to a concrete type. For example:</div></div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">extension Array <b class="">where Element == String</b> {</font></div><div class=""><font face="Menlo" class=""> func makeSentence() -> String {</font></div><div class=""><font face="Menlo" class=""> // uppercase first string, concatenate with spaces, add a period, whatever</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">This is a highly-requested feature that fits into the existing syntax and semantics. Note that one could imagine introducing new syntax, e.g., extending “Array<String>”, which gets into new-feature territory: see the section on “Parameterized extensions”.</div></div></div></blockquote><div><br class=""></div><div>Seems useful.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><b class=""><font size="4" class="">Parameterizing other declarations</font></b></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><i style="font-size: 14px;" class="">Parameterized extensions</i></div><div class=""><br class=""></div><div class="">Extensions themselves could be parameterized, which would allow some structural pattern matching on types. For example, this would permit one to extend an array of optional values, e.g.,</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">extension<b class=""><T></b> Array <b class="">where Element == T?</b> {</font></div><div class=""><font face="Menlo" class=""> var someValues: [T] {</font></div><div class=""><font face="Menlo" class=""> var result = [T]()</font></div><div class=""><font face="Menlo" class=""> for opt in self {</font></div><div class=""><font face="Menlo" class=""> if let value = opt { result.append(value) }</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> return result</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class=""><div class="">We can generalize this to a protocol extensions:</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><font face="Menlo" class="">extension<b class=""><T></b> Sequence <b class="">where Element == T?</b> {</font></div></div></div><div class=""><div class=""><font face="Menlo" class=""> var someValues: [T] {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> var result = [T]()</font></div></div><div class=""><div class=""><font face="Menlo" class=""> for opt in self {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> if let value = opt { result.append(value) }</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return result</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote></div></blockquote><div><br class=""></div><div>This would be fantastic. I’ve run into it a number of times.</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class=""><br class=""></div></blockquote></div><div class=""><font size="4" class=""><b class="">Minor extensions</b><br class=""></font><br class=""></div><div class="">There are a number of minor extensions we can make to the generics system that don’t fundamentally change what one can express in Swift, but which can improve its expressivity.</div><div class=""><br class=""></div><div class=""><span style="font-size: 14px;" class=""><i class="">*Arbitrary requirements in protocols<br class=""></i></span></div><div class=""><br class=""></div><div class="">Currently, a new protocol can inherit from other protocols, introduce new associated types, and add new conformance constraints to associated types (by redeclaring an associated type from an inherited protocol). However, one cannot express more general constraints. Building on the example from “Recursive protocol constraints”, we really want the element type of a Sequence’s SubSequence to be the same as the element type of the Sequence, e.g.,</div><div class=""><br class=""></div><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">protocol Sequence {</font></div><div class=""><font face="Menlo" class=""> associatedtype Iterator : IteratorProtocol</font></div><div class=""><span style="font-family: Menlo;" class=""> …</span></div><div class=""><font face="Menlo" class=""> </font><span style="font-family: Menlo;" class="">associatedtype</span><font face="Menlo" class=""> SubSequence :<b class=""> </b>Sequence<b class=""> where SubSequence.Iterator.Element == Iterator.Element</b></font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote></div><div class=""><br class=""></div><div class="">Hanging the where clause off the associated type is protocol not ideal, but that’s a discussion for another thread.</div></div></blockquote><div><br class=""></div><div>Definitely run into this one before.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><div class=""><br class=""></div><div class=""><span style="font-size: 14px;" class=""><i class="">Default generic arguments </i></span></div></div><div class=""><br class=""></div><div class="">Generic parameters could be given the ability to provide default arguments, which would be used in cases where the type argument is not specified and type inference could not determine the type argument. For example:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">public final class Promise<Value, Reason=Error> { … }</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">func getRandomPromise() -> Promise<Int, ErrorProtocol> { … }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">var p1: Promise<Int> = …</font></div><div class=""><font face="Menlo" class="">var p2: Promise<Int, Error> = p1 <i class="">// okay: p1 and p2 have the same type Promise<Int, Error></i></font></div><div class=""><font face="Menlo" class="">var p3: Promise = getRandomPromise() <i class="">// p3 has type </i></font><span style="font-family: Menlo;" class=""><i class="">Promise<Int, ErrorProtocol> due to type inference</i></span></div></blockquote><div class=""><br class=""></div></div></blockquote><div><br class=""></div><div>Also quite useful in eliminating boilerplate.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><i style="font-size: 14px;" class="">Generalized “class” constraints</i></div><div class=""><br class=""></div><div class="">The “class” constraint can currently only be used for defining protocols. We could generalize it to associated type and type parameter declarations, e.g.,</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">protocol P {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> associatedtype A : class</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">func foo<T : class>(t: T) { }</font></div></div></blockquote><div class=""><br class=""></div><div class="">As part of this, the magical <font face="Menlo" class="">AnyObject</font> protocol could be replaced with an existential with a class bound, so that it becomes a typealias:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">typealias AnyObject = protocol<class></font></div></blockquote><div class=""><br class=""></div><div class="">See the “Existentials” section, particularly “Generalized existentials”, for more information.</div></div></blockquote><div><br class=""></div><div>Another +1. </div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><b class=""><font size="4" class="">Major extensions to the generics model</font></b></div><div class=""><b class=""><br class=""></b></div><div class="">Unlike the minor extensions, major extensions to the generics model provide more expressivity in the Swift generics system and, generally, have a much more significant design and implementation cost.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><i style="font-size: 14px;" class="">*Conditional conformances<br class=""></i></div><div class=""><br class=""></div><div class=""><br class=""></div></div></blockquote><div><br class=""></div><div>This one seems extremely important and has immediate utility IMHO.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><b class=""><font size="4" class="">Syntactic improvements</font></b></div><div class=""><br class=""></div><div class=""><div class=""><br class=""></div></div><div class=""><br class=""></div><div class=""><b class=""><font size="4" class="">Maybe</font></b></div><div class=""><br class=""></div><div class=""><div class=""><br class=""></div></div><div class=""><span style="font-size: 14px;" class=""><i class="">Higher-kinded types<br class=""></i></span></div><div class=""><br class=""></div><div class="">Higher-kinded types allow one to express the relationship between two different specializations of the same nominal type within a protocol. For example, if we think of the Self type in a protocol as really being “Self<T>”, it allows us to talk about the relationship between “Self<T>” and “Self<U>” for some other type U. For example, it could allow the “map” operation on a collection to return a collection of the same kind but with a different operation, e.g.,</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">let intArray: Array<Int> = …</font></div><div class=""><font face="Menlo" class="">intArray.map { String($0) } <i class="">// produces Array<String></i></font></div><div class=""><font face="Menlo" class="">let intSet: Set<Int> = …</font></div><div class=""><font face="Menlo" class="">intSet.map { String($0) } <i class="">// produces Set<String></i></font></div></blockquote><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Potential syntax borrowed from <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002736.html" class="">one thread on higher-kinded types</a> uses ~= as a “similarity” constraint to describe a Functor protocol:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">protocol Functor {</font></div><div class=""><font face="Menlo" class=""> associatedtype A</font></div><div class=""><font face="Menlo" class=""> func fmap<FB where <b class="">FB ~= Self</b>>(f: A -> FB.A) -> FB</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div></div></blockquote><div><br class=""></div><div>I don’t think everyday Swift developers will find much use for this feature, but I do think it enables library authors to do some really powerful things with less boilerplate… though your `map` example is actually compelling in and of itself. My own SequenceTypes get map for free, but only the one that returns an array. That’s a bummer.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><div class=""><span style="font-size: 14px;" class=""><i class="">Specifying type arguments for uses of generic functions</i></span></div></div><div class=""><br class=""></div><div class="">The type arguments of a generic function are always determined via type inference. For example, given:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">func f<T>(t: T)</font></div></blockquote><div class=""><br class=""></div><div class="">one cannot directly specify T: either one calls “f” (and T is determined via the argument’s type) or one uses “f” in a context where it is given a particular function type (e.g., “let x: (Int) -> Void = f” would infer T = Int). We could permit explicit specialization here, e.g.,</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">let x = f<Int> // x has type (Int) -> Void</font></div></blockquote></div></blockquote><div><br class=""></div><div>This is one of those annoying little things that can be really helpful and it seems odd that constructors allow specialization but function calls don’t. It’s also a much cleaner way of resolving ambiguity if the compiler is confused.</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><div class=""><b class=""><font size="4" class="">Potential removals</font></b></div><div class=""><br class=""></div><div class=""><span style="font-size: 14px;" class=""><i class="">Associated type inference</i></span></div></div><div class=""><br class=""></div><div class="">Associated type inference is the process by which we infer the type bindings for associated types from other requirements. For example:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">protocol IteratorProtocol {</font></div><div class=""><font face="Menlo" class=""> associatedtype Element</font></div><div class=""><font face="Menlo" class=""> mutating func next() -> Element?</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">struct IntIterator : IteratorProtocol {</font></div><div class=""><font face="Menlo" class=""> mutating func next() -> Int? { … } // use this to infer Element = Int</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Associated type inference is a useful feature. It’s used throughout the standard library, and it helps keep associated types less visible to types that simply want to conform to a protocol. On the other hand, associated type inference is the only place in Swift where we have a <b class="">global</b> type inference problem: it has historically been a major source of bugs, and implementing it fully and correctly requires a drastically different architecture to the type checker. Is the value of this feature worth keeping global type inference in the Swift language, when we have deliberatively avoided global type inference elsewhere in the language?</div></div></blockquote><div><br class=""></div><div>I’m totally fine to see it go away. I’ve already gotten into the habit of specifying the types explicitly (due to nonsense errors thrown when the compiler can’t properly infer it). It feels slightly strange because the type inference is spooky action at a distance (especially if the protocol conformance happens in an extension).</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><b class=""><font size="4" class="">Existentials</font></b><br class=""><br class="">Existentials aren’t really generics per se, but the two systems are closely intertwined due to their mutable dependence on protocols.<br class=""><br class=""><span style="font-size: 14px;" class=""><i class="">*Generalized existentials</i></span></div><div class=""><br class=""></div><div class="">The restrictions on existential types came from an implementation limitation, but it is reasonable to allow a value of protocol type even when the protocol has Self constraints or associated types. For example, consider IteratorProtocol again and how it could be used as an existential:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">protocol IteratorProtocol {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> associatedtype Element</font></div></div><div class=""><div class=""><font face="Menlo" class=""> mutating func next() -> Element?</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let it: IteratorProtocol = …</font></div><div class=""><font face="Menlo" class="">it.next() // if this is permitted, it could return an “Any?”, i.e., the existential that wraps the actual element</font></div></blockquote><div class=""><font face="Menlo" class=""><br class=""></font></div><div class="">Additionally, it is reasonable to want to constrain the associated types of an existential, e.g., “a Sequence whose element type is String” could be expressed by putting a where clause into “protocol<…>” or “Any<…>” (per “Renaming protocol<…> to Any<…>”):</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">let strings: Any<Sequence<b class=""> where .Iterator.Element == String</b>> = [“a”, “b”, “c”]</font></div></blockquote><div class=""><br class=""></div><div class="">The leading “.” indicates that we’re talking about the dynamic type, i.e., the “Self” type that’s conforming to the Sequence protocol. There’s no reason why we cannot support arbitrary “where” clauses within the “Any<…>”. This very-general syntax is a bit unwieldy, but common cases can easily be wrapped up in a generic typealias (see the section “Generic typealiases” above):</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">typealias AnySequence<Element> = <b class="">Any<Sequence where .Iterator.Element == Element></b></font></div><div class=""><font face="Menlo" class="">let strings: AnySequence<String> = [“a”, “b”, “c”]</font></div></blockquote><div class=""><br class=""></div></div></blockquote><div><br class=""></div><div>Free opinions on the internet are worth what you pay for them, but I’ll just say that if I were in charge of the Swift 3 schedule it wouldn’t ship without this feature. I feel extremely strongly that this is necessary to round out generics support. Trying to write an app that is heavily protocol-oriented and makes use of lots of generics runs into existential (ha!) walls constantly. It forces you to choose 100% anything-goes-dynamic (ala Objective-C) or jump through tons of hoops to get type safety.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><i style="font-size: 14px;" class="">Opening existentials</i></div><div class=""><br class=""></div><div class="">Generalized existentials as described above will still have trouble with protocol requirements that involve Self or associated types in function parameters. For example, let’s try to use Equatable as an existential:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">protocol Equatable {</font></div><div class=""><font face="Menlo" class=""> func ==(lhs: Self, rhs: Self) -> Bool</font></div><div class=""><font face="Menlo" class=""> func !=(lhs: Self, rhs: Self) -> Bool</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let e1: Equatable = …</font></div><div class=""><font face="Menlo" class="">let e2: Equatable = …</font></div><div class=""><font face="Menlo" class="">if e1 == e2 { … } <i class="">// <b class="">error</b>:</i> e1 and e2 don’t necessarily have the same dynamic type</font></div></blockquote><div class=""><br class=""></div><div class="">One explicit way to allow such operations in a type-safe manner is to introduce an “open existential” operation of some sort, which extracts and gives a name to the dynamic type stored inside an existential. For example:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span> </div><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><font face="Menlo" class="">if let storedInE1 = e1 openas T { // T is a the type of storedInE1, a copy of the value stored in e1</font></blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><font face="Menlo" class=""> if let storedInE2 = e2 as? T { // is e2 also a T?</font></blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><font face="Menlo" class=""> if storedInE1 == storedInE2 { … } // okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable</font></blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><font face="Menlo" class=""> }</font></blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><font face="Menlo" class="">}</font></blockquote></div></div></blockquote><br class=""></div><div>Everything on existentials gets a huge +1 from me.</div><div><br class=""></div><div><br class=""></div><div><br class=""></div><div>Overall I’d rate conditional conformance, parameterized extensions, and generalized existentials as the highest priority items. </div><div><br class=""></div><div>Generalized existentials have no effective workarounds and they have a huge impact on the design of API contracts and even how you use protocols themselves so they are a big pain point for me personally.</div><div><br class=""></div><div><br class=""></div>Russ<div class=""><br class=""></div></body></html>