<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 12, 2017, at 3:23 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 12 Mar 2017, at 14:32, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class="">This is a really important feature IMO, but as others have pointed out it basically amounts to higher-kinded types. &nbsp;I would love to be wrong about this but I am reasonably sure this is out of scope for Swift 4 (otherwise I would be working on a proposal already).<br class=""><br class="">Sent from my iPad</div><div class=""><br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">I’m not an expert on this stuff, but are they still higher-kinded types if we don’t express a relationship between Self and the associated type? I don’t think it’s quite the same conceptual leap as HKT.</div></div></div></div></blockquote><div><br class=""></div><div>I’m no expert either but it sure seems to me like it enables the things usually discussed in the context of higher-kinder types. &nbsp;Maybe someone from the core team can comment on whether there is a meaningful difference and whether this is something that could fit into Swift 4.</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=""><br class=""></div><div class="">Consider that every associated type must be backed by a typealias (explicit or inferred) in the conforming type. We can already have generic typealiases. This would be a more targeted thing which required those associatedtype-implementing-typealiases to contain generic parameters. It would also extend the constraints from SE-0142 to allow constraints to refer to those parameters and bind them to other associated types.</div><div class=""><br class=""></div><div class="">The workaround is basically to erase and dynamic-cast your way out:</div></div></div></div></blockquote><div><br class=""></div><div>Yes, there are workarounds, none of which are desirable. &nbsp;</div><div><br class=""></div><div>I ran into a case last year where there was a significant performance impact caused by the need to perform type erasure as a workaround. &nbsp;The type erasing wrapper required an allocation and type information that could have been used by the optimizer was lost. &nbsp;This was frustrating and convinced me that we definitely need HKT in Swift eventually. &nbsp;There are very useful generic libraries that cannot be implemented efficiently without them.</div><div><br class=""></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=""><br class=""></div><div class=""><span style="font-family: Courier;" class="">&nbsp; &nbsp; &nbsp; //NOTE: dynamic type of ScanPromise.Result *must* be same as closure result. No static enforcement though :(</span></div><div class=""><span style="font-family: Courier;" class=""><br class=""></span></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><font face="Courier" class="">extension Scanner where ScanPromise.Result == Any? {</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; func scan&lt;T&gt;(from f: Offset, until u: (Offset, Item) -&gt; T?) -&gt; T? {</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; &nbsp; &nbsp; return withoutActuallyEscaping(u) { _u -&gt; T? in</font></div></div></div></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return promiseScan(from: f, until: _u).await() as? T // downcast from Any? to T?</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; }</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">}</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class=""><br class=""></font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">class MyPromise&lt;R&gt;: Promise {</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; typealias Result = R?</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; let offset: Offset</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; let block: (Offset, Item) -&gt; R?</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">}</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class=""><br class=""></font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">class MyScanner: Scanner {</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; typealias ScanPromise = MyPromise&lt;Any&gt; // want this to be “typealias ScanPromise&lt;X&gt; = MyPromise&lt;X&gt;"</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class=""><br class=""></font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; func promiseScan&lt;T&gt;(from: Offset, until: @escaping (Offset, Item) -&gt; T?) -&gt; ScanPromise {</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; &nbsp; &nbsp; return MyPromise(offset: from, block: until) // upcast from T? to Any?</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">&nbsp; &nbsp; }</font></div></div></div><div class=""><div class=""><div class=""><font face="Courier" class="">}</font></div></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">- Karl</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class="">On Mar 11, 2017, at 11:49 PM, Karl Wagner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class="">I have a model like this:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">protocol Promise {</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; associatedtype Result</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">protocol Scanner {</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; associatedtype ScanPromise: Promise</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; func promiseScan&lt;T&gt;(from: Offset, until: (Offset, Item) -&gt; T?) -&gt; ScanPromise // where Result == T?</font></div><div class=""><font face="Courier" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">The thing that I’m trying to express is: whichever type implements the associated type ‘ScanPromise’ must be generic, and that parameter must be its result (i.e. something it got as a result of calling the “until” closure).</div><div class=""><br class=""></div><div class="">Even with SE-0142, this kind of constraint would not be possible. What I would like to write is something like this:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier" class="">protocol Promise {</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; associatedtype Result</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">protocol Scanner {</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; associatedtype ScanPromise&lt;T&gt;: Promise // now generic. [SE-0142]: where Result == T</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; func promiseScan&lt;T&gt;(from: Offset, until: (Offset, Item) -&gt; T?) -&gt; ScanPromise&lt;T&gt;</font></div><div class=""><font face="Courier" class="">}</font></div></div><div class=""><br class=""></div><div class="">Thoughts?</div><div class=""><br class=""></div><div class="">- Karl</div></div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>