<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div>Changing all typealiases in protocols to generic arguments is a pretty significant change to the language, with a very large impact on existing code. It also opens the door to implementing the same protocol with different types, which is something that Swift does not currently allow.<br></div>
<div> </div>
<div>I think Rust's trait system is a good example of the right way to do this. Rust traits are like Swift protocols, but they started out with only generics, no associated types. Later on they gained associated types as well (with the same limitation that Swift protocols have, where any trait with an associated type cannot be used as a "trait object"). The end result is Rust traits can have both generics and associated types, and the choice of which to use depends on what it's for. Also, a type in Rust can implement the same trait with different generic parameters (but for any parameterized trait, it can only have one implementation regardless of associated types). This is also how Rust has implemented multi-dispatch (Rust does not have method overloading in general). And the way you're supposed to think about this is generic type parameters to a trait are "input types", and associated types are "output types". So any given type can implement the same protocol as many times as it wants with distinct input types, but for every set of input types, there is only one set of output types. And this works very well.<br></div>
<div> </div>
<div>An example of how this is used is the trait that powers the + operator, called std::ops::Add. It's defined as<br></div>
<div> </div>
<pre class="rust trait">pub trait Add<RHS = Self> {
type Output;
fn <a href="https://doc.rust-lang.org/stable/std/ops/trait.Add.html#tymethod.add" class="fnname">add</a>(self, rhs: RHS) -> Self::<a class="trait" href="https://doc.rust-lang.org/stable/std/ops/trait.Add.html" title="std::ops::Add">Output</a>;
}<br></pre><div> </div>
<div>(the `= Self` bit is a defaulted type parameter)<br></div>
<div> </div>
<div>This means that for any given type T, it can support addition with any number of other types, but for every pair of types (T,U), the expression `T + U` can only ever have one return value. To demonstrate how this would work in Swift, you can imagine supporting `+` with NSNumber against different numeric types:<br></div>
<div> </div>
<div>extension NSNumber: Add<Int> {<br></div>
<div> typealias Output = Int<br></div>
<div> func add(rhs: Int) -> Int {<br></div>
<div> return integerValue + rhs<br></div>
<div> }<br></div>
<div>}<br></div>
<div> </div>
<div>extension NSNumber: Add<UInt> {<br></div>
<div> typealias Output = UInt<br></div>
<div> func add(rhs: UInt) -> UInt {<br></div>
<div> return unsignedIntegerValue + rhs<br></div>
<div> }<br></div>
<div>}<br></div>
<div> </div>
<div>// etc...<br></div>
<div> </div>
<div>Besides the clean distinction between "input" and "output" types, this also allows various traits to have only one or the other. For example, Rust's equivalent to Swift's Generator is std::iter::Iterator, which has an associated type for the iterated element. And it makes a lot of sense for Iterator to use an associated type for this instead of a type parameter, because it's confusing to have a sequence that can yield multiple different element types from a call to `seq.generate()` (or in Rust's case, `seq.iter()`) which would require an explicit type annotation. And it's even worse when you realize that most code that iterates over sequences doesn't even care about the concrete generator type, but the type annotation requires declaring that concrete type (the alternative, declaring it as `GeneratorType<T>`, will wrap the concrete type in a protocol object and incur the overhead of extra allocation + dynamic function dispatch if the optimizer can't remove it).<br></div>
<div> </div>
<div>tl;dr: I want both type parameters and associated types for protocols<br></div>
<div> </div>
<div>-Kevin Ballard<br></div>
<div> </div>
<div>On Thu, Dec 3, 2015, at 02:39 PM, David Hart wrote:<br></div>
<blockquote type="cite"><div>I have been waiting a long time for something like this. I’m 100% behind this.<br></div>
<div><div> </div>
<div><blockquote type="cite"><div>On 03 Dec 2015, at 23:12, Tal Atlas <<a href="mailto:me@tal.by">me@tal.by</a>> wrote:<br></div>
<div> </div>
<div><div dir="ltr"><div>With the awesome expansion of protocol oriented programming that swift has allowed, the lack of generic protocols has felt noticeably lacking and painful in some cases. I made an in depth proposal here: <a style="color:rgb(42, 128, 185);text-decoration:none;font-family:Slack-Lato, appleLogo, sans-serif;font-size:15px;" href="https://github.com/tal/swift-evolution/blob/tal/generic-protocol-proposal/proposals/NNNN-add-generic-protocols.md">https://github.com/tal/swift-evolution/blob/tal/generic-protocol-proposal/proposals/NNNN-add-generic-protocols.md</a><br></div>
<div> </div>
<div>But the tl;dr is this:<br></div>
<div> </div>
<div><div>protocol Validator<TypeToValidate> {<br></div>
<div> var value: TypeToValidate { get set }<br></div>
<div> var valueIfValid: TypeToValidate? { get }<br></div>
<div>}<br></div>
<div> </div>
<div>struct FooStringValidator: Validator<String> {<br></div>
<div> //... implementation<br></div>
<div>}<br></div>
<div> </div>
<div>let stringValidator: Validator<String><br></div>
</div>
<div> </div>
<div>Look forward to hearing some feedback.<br></div>
</div>
<div><img style="height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-bottom:0px !important;margin-right:0px !important;margin-left:0px !important;padding-top:0px !important;padding-bottom:0px !important;padding-right:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/c961b38ddbe1869a64f4ab0354c19902767a633e34cbedf8fe19f5cfcd971149/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3e654932787358514537443b687374565b67667433386857796a73533f423a7630375775617f6d6942746a6242593d4c447052635943727e4138723a454d654f6a544a41367e415b445679657951376a747d223242537d4d6f61637665613b6262307a4169677e4d22364b4c6750363332317e62684f415a4755385f4678353f6154514071715d22364971695658534a6635417e457e615a536562517137544a763435326a4d654234577540597c41726730386775477671336455393a5634725a4638426a653e667372696378426a5a4c6342597839497942516a79786f47745371523b4e634631334a457c40384057794d23344/open" >
_______________________________________________<br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div>https://lists.swift.org/mailman/listinfo/swift-evolution<br></div>
</div>
</blockquote></div>
</div>
<div><img style="height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-bottom:0px !important;margin-right:0px !important;margin-left:0px !important;padding-top:0px !important;padding-bottom:0px !important;padding-right:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/2737105a9558e00bdee63387760219e0f4ecb7261c6171fcfd18611dc4d02696/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e465a797a5768687378483a7676695856647554626d223247445859744675525c6e4368766f636d22324d6533587c627d47484766486f617d22324f66695163455c487332514456597a536073687e6831345244515a74717f6754695e697151356237714c6433765e4a6d22324349307241464151485456494e44413442795431587d22364848334c6473367645727d6b644f6a656964334d48464e61524d465476797635357e49756d22324a53585f65493c623e6a4877637b624c685c643b443a5e44556d6246756856335f614d23344d23344/open" ><br></div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div> </div>
</body>
</html>