<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 May 27, 2016, at 7:08 AM, Thorsten Seitz &lt;<a href="mailto:tseitz42@icloud.com" class="">tseitz42@icloud.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">Am 25.05.2016 um 22:16 schrieb Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt;:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class=""><blockquote type="cite" class="">On May 25, 2016, at 2:22 PM, Brent Royal-Gordon &lt;<a href="mailto:brent@architechies.com" class="">brent@architechies.com</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class="">But if we are going to remove the ability to use typealiases bound to `Any` in constraints we need to introduce an alternative mechanism for factoring out constraints (hopefully a superior mechanism that can abstract over constraints that relate generic parameters to each other).<br class=""></blockquote><br class="">I could certainly imagine having, for instance, a `constraintalias` keyword:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>constraintalias HashableAndComparable = Hashable, Comparable<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>constraintalias CollectionOfConforming&lt;ElementConstraint&gt; = Collection where .Element: ElementConstraint<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let value: Any&lt;HashableAndComparable&gt; = 123<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func sum&lt;C: CollectionOfConforming&lt;Integer&gt;&gt;(numbers: C) -&gt; C.Iterator.Element {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>return numbers.reduce(0, combine: +)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""></blockquote><br class="">If we do something specific to generic constraints I would prefer to see something that generalizes to support cases where you want to accept two types that both conform to `Sequence`, `Collection`, etc and both have the same `Element` (or any other constraint that relates associated types from more than one type argument). &nbsp;It could be similar to what you have, but slightly more generalized.<br class=""><br class=""><br class="">func sum<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;T, C1, C2<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where C1: Sequence, C2: Sequence, C1.Iterator.Element == T, C2.Iterator.Element == T&gt;<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(c1: C1, c2: C2, op: (T, T) -&gt; T) -&gt; [T] {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return zip(c1, c2).map(op)<br class="">}<br class=""><br class="">This would allow me to write something along the lines of:<br class=""><br class="">func zipMap<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;S1, S2 where SameElementSequences&lt;S1, S2&gt;&gt;<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(s1:S1, s2: S2, op: (S1.Element, S2.Element) -&gt; S1.Element) -&gt; [S1.Element] {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return zip(s1, s2).map(op)<br class="">}<br class=""><br class="">So what syntax do we use to define something like `SameElementSequences&lt;S1, S2 &gt;`? &nbsp;It is effectively a predicate that returns true if all of the constraints it defines are satisfied. &nbsp;It could be similar to what you have above, but we would need to allow for more than one “constrainee”.<br class=""><br class="">Maybe it would look something like this:<br class=""><br class="">constraint SameElementSequences S1, S2 =<span class="Apple-converted-space">&nbsp;</span><br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;S1: Sequence, S2: Sequence<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where S1.Element == S2.Element<br class=""></div></div></blockquote><div class=""><br class=""></div>That’s a good example! Now this is beginning to make sense (or now I’m starting to understand it :-)</div></div></blockquote><div><br class=""></div><div>Great!</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Side note: I would prefer zipMap being defined more generally which unfortunately renders this obsolete as an example for abstracted constraints as none are needed anymore:</div></div></blockquote><div><br class=""></div><div>Yeah, I wasn’t trying to provide the best / most general design for `zipMap`. &nbsp;I chose a signature that would demonstrate how you might want to abstract over constraints that apply to more than one constrainee. &nbsp;It was the first thing that came to mind. &nbsp;:-)</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">func zipMap&lt;S1: Sequence, S2: Sequence, Result&gt;</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>(s1: S1, s2: S2, op: (S1.Element, S2.Element) -&gt; Result) -&gt; [Result] {</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>return zip(s1, s2).map(op)</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">}</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">But we might want to create a generic subtraction function like follows which could make use of the constraint you defined further down:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">func subtract&lt;S1, S2, E where SequencesOf&lt;E, S1, S2&gt;, E: Equatable&gt;</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>(s1: S1, s2: S2) -&gt; [E] {</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// answer array containing all elements of s1 which are not in s2</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">}</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Note that `E` is not a concrete type argument here. I’m not sure whether it makes sense to distinguish between `Type` and `Constrainee` as these kinds are simply a result of supplying either a concrete type or a type parameter:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">constraint SequencesOf&lt;Element, S1, S2&gt; =<br class="">&nbsp; &nbsp; &nbsp; &nbsp;S1: Sequence, S2: Sequence<br class="">&nbsp; &nbsp; &nbsp; &nbsp;where S1.Element == Element, S2.Element == Element</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Regardless whether Element, S1 or S2 are concrete types or type parameters, the constraint can simply be checked whether it holds.</div></div></blockquote><div><br class=""></div><div>The reason it matters is that you *must* pass something that can be constrained to a `Constrainee` argument. &nbsp;You *cannot* pass a concrete type. &nbsp;This could be inferred, but I think that would fall into the same category as inference across a function signature, which Swift is specifically avoiding. &nbsp;Thus the “kind” specification.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Maybe we could change the syntax a little bit:</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><b class="">constraint</b><span class="Apple-converted-space">&nbsp;</span>SequencesOf&lt;Element, S1, S2&gt;<span class="Apple-converted-space">&nbsp;</span><b class="">where</b><span class="Apple-converted-space">&nbsp;</span>S1: Sequence, S2: Sequence, S1.Element == Element, S2.Element == Element</div><div class=""><br class=""></div><div class="">which might alternatively be written as:</div><div class=""><br class=""></div><div class=""><div class=""><b class="">constraint</b><span class="Apple-converted-space">&nbsp;</span>SequencesOf&lt;Element,&nbsp;S1: Sequence,&nbsp;S2: Sequence&gt;&nbsp;<b class="">where</b><span class="Apple-converted-space">&nbsp;</span>S1.Element == Element, S2.Element == Element</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">This would distinguish constraints better from typealiases. Otherwise a simple constraint would look like a typealias:</div><div class=""><br class=""></div><div class="">constraint SequenceOf&lt;Element, S&gt; = S where S: Sequence, Element == S.Element</div><div class=""><br class=""></div><div class="">vs.</div><div class=""><br class=""></div><div class="">constraint SequenceOf&lt;Element, S&gt; where S: Sequence, Element == S.Element</div></div></div></blockquote><div><br class=""></div><div>I avoided angle brackets on the arguments because I think it’s more readable without them. &nbsp;But there is a good case to be made that angle brackets should be used for compile-time parameters in Swift. &nbsp;This syntax works for me. &nbsp;</div><div><br class=""></div><div>One thing that just occurred to me when looking at your example:</div><div><br class=""></div><div>constraint&nbsp;SequencesOf&lt;Element, S1: <b class="">Sequence</b>, S2: <b class="">Sequence</b>&gt;&nbsp;where&nbsp;S1.Element == Element, S2.Element ==&nbsp;Element</div><div><br class=""></div><div>I wonder if we would ever need the ability to pass a constrained but concrete type to a constraint abstraction. &nbsp;I can’t quickly think of any examples where we would. &nbsp;If we don’t need the ability to do this, we could easily infer that `S1` and `S2` are of kind `Constrainee` because they are constrained in the signature. &nbsp;We could also say that the default kind is `Type`. &nbsp;This would minimize the need to state and think explicitly about kinds.</div><div><br class=""></div><div>-Matthew</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">-Thorsten</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">If we want to allow concrete types and higher order constraints to be passed we would have to specify “kinds” for the arguments to the constraints. &nbsp;We might say `Constrainee` for an argument that is getting constrained, `Type` for a concrete type argument and `Constraint` for a higher order constraint that applies to a single type and something like function type syntax for multi-argument higher order constraints: `(Type, Constrainee, Constraint) -&gt; Constraint` or something like that.<br class=""><br class="">This would let us do something like:<br class=""><br class="">constraint SequencesOf Element: Type, S1: Constrainee, S2: Constrainee =<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;S1: Sequence, S2: Sequence<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where S1.Element == Element, S2.Element == Element<br class=""><br class="">Used like this:<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">func intZipMap<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;S1, S2 where SequencesOf&lt;Int, S1, S2&gt;&gt;<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(s1:S1, s2: S2, op: (Int) -&gt; Int) -&gt; [Int] {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return zip(s1, s2).map(op)<br class="">}<br class=""><br class="">We could allow shorthand for simple constraints where the “kinds” are omitted and assumed to be `Constrainee`.<br class=""><br class="">Ideally we would be able to overload constraints so we could use the name “SequencesOf” for a constraint that accepts three sequences, etc.<br class=""><br class="">I think I prefer `constraint` rather than `constraintalias` but am open to arguments for both of them.<br class=""><br class="">I like that you are allowed a `constraintalias` to be used as an existential. &nbsp;That would still work for single argument constraints in the generalized form I am suggesting.<br class=""><br class="">I’m just spitballing on syntax and keyword names here to try and communicate the capability that I think we should strive for. &nbsp;I’m interested in hearing everyone’s thoughts on this…<br class=""><br class="">-Matthew<br class=""><br class=""><blockquote type="cite" class=""><br class="">--<span class="Apple-converted-space">&nbsp;</span><br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class=""></blockquote><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></div></blockquote></div></div></blockquote></div><br class=""></body></html>