<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 Apr 24, 2017, at 2:38 PM, Kevin Nattinger &lt;<a href="mailto:swift@nattinger.net" class="">swift@nattinger.net</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><br class=""></div><div class="">How can I improve your understanding?</div><br class=""></div></div></blockquote></div><div class=""><br class=""></div>Given the enum I was using earlier:<div class=""><br class=""><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">enum</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Thing {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">case</span><span style="font-variant-ligatures: no-common-ligatures" class=""> thingOne&lt;T&gt;(T)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">case</span><span style="font-variant-ligatures: no-common-ligatures" class=""> thingTwo&lt;T&gt;(T)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div></div><div class=""><br class=""></div><div class="">- Write a function that takes a&nbsp;<span style="font-family: Menlo; font-size: 11px;" class="">thingOne&lt;String&gt; </span>or<span style="font-family: Menlo; font-size: 11px;" class="">&nbsp;</span><span style="font-family: Menlo; font-size: 11px;" class="">thingTwo&lt;Int&gt; </span>but nothing else.</div></div></div></div></blockquote><div><br class=""></div><div>This isn’t possible since generic types introduced on cases are erased in the type of `Thing`.</div><div><br class=""></div><div>We can actually already achieve what you want by moving the generics onto the type itself, and this is already possible in Swift! No new features are necessary.</div><div><br class=""></div><div>```</div><div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 11px;" class=""><span style="color: rgb(201, 0, 164);" class="">enum</span>&nbsp;Thing<span style="color: rgb(200, 0, 164);" class="">&lt;</span>T1, T2<span style="color: rgb(200, 0, 164);" class="">&gt;</span>&nbsp;{</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">case</span>&nbsp;thingOne(T1)</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">case</span>&nbsp;thingTwo(T2)</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">}</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; min-height: 17px; font-size: 11px;" class=""><br class=""></div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 11px;" class=""><span style="color: rgb(201, 0, 164);" class="">func</span>&nbsp;test(_ x: Thing<span style="color: rgb(200, 0, 164);" class="">&lt;</span><span style="color: rgb(121, 14, 173);" class="">String</span>,&nbsp;<span style="color: rgb(121, 14, 173);" class="">Int</span><span style="color: rgb(200, 0, 164);" class="">&gt;</span>) {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">switch</span>&nbsp;x {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">case</span>&nbsp;<span style="color: rgb(200, 0, 164);" class="">.</span>thingOne(<span style="color: rgb(201, 0, 164);" class="">let</span>&nbsp;s):</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; color: rgb(223, 0, 2); font-size: 11px;" class=""><span style="color: rgb(0, 0, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span style="color: rgb(69, 0, 132);" class="">print</span><span style="color: rgb(0, 0, 0);" class="">(</span>"The string has value \(s)!"<span style="color: rgb(0, 0, 0);" class="">)</span></div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">case</span>&nbsp;<span style="color: rgb(200, 0, 164);" class="">.</span>thingTwo(<span style="color: rgb(201, 0, 164);" class="">let</span>&nbsp;i):</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; color: rgb(223, 0, 2); font-size: 11px;" class=""><span style="color: rgb(0, 0, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span style="color: rgb(69, 0, 132);" class="">print</span><span style="color: rgb(0, 0, 0);" class="">(</span>"The int has value \(i)!"<span style="color: rgb(0, 0, 0);" class="">)</span></div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">&nbsp; &nbsp;&nbsp;}</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 11px;" class="">}</div></div><div>```</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">- Declare a variable that can hold a&nbsp;<span style="font-family: Menlo; font-size: 11px;" class="">thingOne&lt;String&gt;&nbsp;</span>or<span style="font-family: Menlo; font-size: 11px;" class="">&nbsp;</span><span style="font-family: Menlo; font-size: 11px;" class="">thingTwo&lt;Int&gt;&nbsp;</span>but nothing else.</div></div></div></div></blockquote><div><br class=""></div><div>With our new definition, we can write:</div><div><br class=""></div><div>```</div><div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 11px;" class=""><span style="color: #c900a4" class="">var</span> x: Thing<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">String</span>, <span style="color: #790ead" class="">Int</span><span style="color: #c800a4" class="">&gt;</span></div></div><div>```</div><div><br class=""></div><div>This variable can be initialized with a `thingOne` containing a `String` payload or a `thingTwo` containing an `Int` payload.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">Or explain why something that is widely used, trivial to write, and necessary for type safety should be removed from the language.</div></div></div></div></blockquote><br class=""></div><div>As I just explained, what you desire is *already possible* in the language. This new features does not address your use case. Instead, this feature allows for type erasure of enum cases. This is pretty similar to storing an existential as a payload. I’m not even sure if it’s sufficiently different to justify its addition to the language.</div><div><br class=""></div><div>The original non-generic definition of `Thing` with generic cases is essentially equivalent to storying `Any` as the case payloads. We can make this more useful by using protocols to constrain the payload type.</div><div><br class=""></div><div>I think this proposal doesn’t really add any useful new capabilities without the ability to constraint the return type. For example, these are nearly equivalent:</div><div><br class=""></div><div>```</div><div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; font-size: 13px; line-height: normal; font-family: Monaco;" class=""><span style="color: #c900a4" class="">enum</span> Key {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; font-size: 13px; line-height: normal; font-family: Monaco;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> hashable<span style="color: #c800a4" class="">&lt;</span>T: <span style="color: #790ead" class="">Hashable</span><span style="color: #c800a4" class="">&gt;</span>(T)</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; font-size: 13px; line-height: normal; font-family: Monaco;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> any<span style="color: #c800a4" class="">&lt;</span>T<span style="color: #c800a4" class="">&gt;</span>(T)</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; font-size: 13px; line-height: normal; font-family: Monaco;" class="">}</div></div><div>```</div><div><br class=""></div><div>vs.</div><div><br class=""></div><div>```</div><div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; font-size: 13px; line-height: normal; font-family: Monaco;" class=""><span style="color: rgb(201, 0, 164);" class="">enum</span>&nbsp;Key {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; font-size: 13px; line-height: normal; font-family: Monaco;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">case</span>&nbsp;hashable(AnyHashable)</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; font-size: 13px; line-height: normal; font-family: Monaco;" class="">&nbsp; &nbsp;&nbsp;<span style="color: rgb(200, 0, 164);" class="">case</span>&nbsp;any(Any)</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; font-size: 13px; line-height: normal; font-family: Monaco;" class="">}</div></div><div>```</div><div><br class=""></div><div>Both of these definitions are nearly equivalent except the former introduces a new generic variable in scope when you match on a constrained case. Is this useful? I’m not sure. Is it breaking type safety? Absolutely not!! If I match the `hashable` case in a switch statement, it’s very similar to if I had written a function with the following signature:</div><div><br class=""></div><div>```</div><div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class=""><span style="color: #c900a4" class="">func</span> matchHashable&lt;T: <span style="color: #790ead" class="">Hashable</span>&gt;(_ x: T) { <span style="color: #c800a4" class="">...</span> }</div></div><div>```</div><div><br class=""></div><div>Because of this, no type safety is lost in the switch statement.</div><div><br class=""></div><div>—</div><div><br class=""></div><div>I think a more interesting version of this proposal would be as follows: Allow where constraints and explicit return type annotations on case declarations. This is very similar to what a&nbsp;<a href="https://en.wikibooks.org/wiki/Haskell/GADT" class="">GADT</a>&nbsp;allows you to do. Check out how cool this example is—and 110% type-safe!</div><div><br class=""></div><div>Below is an example of a data structure representing a computation. We can inspect is since it is just data, but we can also evaluate it to see the result.</div><div><br class=""></div><div>```</div><div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class=""><span style="color: #c900a4" class="">enum</span> Expression<span style="color: #c800a4" class="">&lt;</span>T<span style="color: #c800a4" class="">&gt;</span> {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> value(T)</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> isEqual(T, T) <span style="color: #c800a4" class="">-&gt;</span> Expression<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">Bool</span><span style="color: #c800a4" class="">&gt;</span> <span style="color: #c800a4" class="">where</span> T: <span style="color: #790ead" class="">Equatable</span></div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> plus(T, T) <span style="color: #c800a4" class="">-&gt;</span> Expression<span style="color: #c800a4" class="">&lt;</span>T<span style="color: #c800a4" class="">&gt;</span> <span style="color: #c800a4" class="">where</span> T: Numeric</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> and(<span style="color: #790ead" class="">Bool</span>, <span style="color: #790ead" class="">Bool</span>) <span style="color: #c800a4" class="">-&gt;</span> Expression<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">Bool</span><span style="color: #c800a4" class="">&gt;</span></div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> not(<span style="color: #790ead" class="">Bool</span>) <span style="color: #c800a4" class="">-&gt;</span> Expression<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">Bool</span><span style="color: #c800a4" class="">&gt;</span></div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; color: rgb(0, 142, 0); font-size: 13px;" class=""><span style="color: #000000" class="">&nbsp; &nbsp; </span>// etc.</div><p style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; min-height: 17px; font-size: 13px;" class="">&nbsp;&nbsp; &nbsp;<br class="webkit-block-placeholder"></p><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; <span style="color: #c900a4" class="">func</span> evaluate() <span style="color: #c800a4" class="">-&gt;</span> T {</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">switch</span> <span style="color: #c800a4" class="">self</span> {</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>value(<span style="color: #c900a4" class="">let</span> x):</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">return</span> x</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>isEqual(<span style="color: #c900a4" class="">let</span> lhs, <span style="color: #c900a4" class="">let</span> rhs):</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; color: rgb(0, 142, 0); font-size: 13px;" class=""><span style="color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// We know that T: Equatable, so we can use `==`</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">return</span> lhs <span style="color: #c800a4" class="">==</span> rhs</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>plus(<span style="color: #c900a4" class="">let</span> lhs, <span style="color: #c900a4" class="">let</span> rhs):</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; color: rgb(0, 142, 0); font-size: 13px;" class=""><span style="color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// We know that T: Numeric, so we can use `+`</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">return</span> lhs <span style="color: #c800a4" class="">+</span> rhs</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>and(<span style="color: #c900a4" class="">let</span> lhs, <span style="color: #c900a4" class="">let</span> rhs):</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">return</span> lhs <span style="color: #c800a4" class="">&amp;&amp;</span> rhs</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>not(<span style="color: #c900a4" class="">let</span> x):</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c800a4" class="">return</span> <span style="color: #c800a4" class="">!</span>x</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">&nbsp; &nbsp; }</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class="">}</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; min-height: 17px; font-size: 13px;" class=""><br class=""></div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class=""><span style="color: #c900a4" class="">let</span> x: Expression<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">Int32</span><span style="color: #c800a4" class="">&gt;</span> <span style="color: #c800a4" class="">=</span> <span style="color: #c800a4" class="">.</span>plus(<span style="color: #c800a4" class="">.</span>value(<span style="color: #3a00dc" class="">3</span>), <span style="color: #c800a4" class="">.</span>value(<span style="color: #3a00dc" class="">10</span>))</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class=""><span style="color: #c900a4" class="">let</span> y: Expression<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">Int32</span><span style="color: #c800a4" class="">&gt;</span> <span style="color: #c800a4" class="">=</span> <span style="color: #c800a4" class="">.</span>plus(<span style="color: #c800a4" class="">.</span>value(<span style="color: #3a00dc" class="">7</span>), <span style="color: #c800a4" class="">.</span>value(<span style="color: #3a00dc" class="">6</span>))</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class=""><span style="color: #c900a4" class="">let</span> z: Expression<span style="color: #c800a4" class="">&lt;</span><span style="color: #790ead" class="">Bool</span><span style="color: #c800a4" class="">&gt;</span> <span style="color: #c800a4" class="">=</span> <span style="color: #c800a4" class="">.</span>isEqual(x, y)</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; min-height: 17px; font-size: 13px;" class=""><br class=""></div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; font-size: 13px;" class=""><span style="color: #450084" class="">print</span>(z<span style="color: #c800a4" class="">.</span>evaluate()) <span style="color: #008e00" class="">// -&gt; true</span></div></div><div>```</div><div class=""><br class=""></div><div class="">Notice that it is impossible to construct an `Expression` of a nonsensical type. Try to do this with the enums we have in Swift today. You’ll have to do some force casting of types. Not pretty.</div><div class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class="">I hope I was able to clarify some things for you. Let me know if you have any other questions.</div><div class=""><br class=""></div><div class="">Cheers,</div><div class="">Jaden Geller</div><div class=""><br class=""></div></body></html>