<div dir="ltr">On Sun, Jan 15, 2017 at 3:27 PM, Dave Abrahams via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
on Sun Jan 15 2017, Xiaodi Wu &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
<br>
&gt; There _may_ be value in recognizing the distinction between rings and<br>
&gt; fields, perhaps? Just as the FP protocols make room for people to implement<br>
&gt; their own decimal FP types, and just as you&#39;re trying to make Arithmetic<br>
&gt; accommodate complex numbers, the distinction would allow someone to write<br>
&gt; algorithms generic over rationals and reals (i.e. fields). Being able to<br>
&gt; represent exact fractions isn&#39;t so terribly niche, and I think the design<br>
&gt; wouldn&#39;t be terribly complicated by its accommodation:<br>
&gt;<br>
&gt; ```<br>
&gt; // rename Arithmetic to Ring<br>
&gt; // it&#39;s acceptable to omit `.one` from Ring, though some may call that a<br>
&gt; Pseudoring<br>
&gt; // consider omitting division from Ring and pushing it down to<br>
&gt; BinaryInteger and Field<br>
&gt;<br>
&gt; protocol BinaryInteger : Ring { ... }<br>
&gt;<br>
&gt; protocol Field : Ring {<br>
&gt;   static var one { get }<br>
&gt;   static func / (Self, Self) -&gt; Self<br>
&gt;   static func /= (inout Self, Self)<br>
&gt;   var inverted: Self { get } // default impl: .one / self<br>
&gt; }<br>
&gt;<br>
&gt; protocol FloatingPoint : Field { ... }<br>
&gt; // rational number types and complex number types<br>
&gt; // would also conform to Field<br>
&gt; ```<br>
<br>
</span>What generic algorithms would this enable?</blockquote><div><br></div><div>For one, anything to do with dividing into equal parts could be generic over floating point, rational, and even complex numbers, but you probably wouldn&#39;t want to include integer types in such an algorithm.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Would they be appropriate<br>
for the standard library (as opposed to some more specialized numerics<br>
library)?<br></blockquote><div><br></div><div>The issue is that it&#39;s not terribly ergonomic to relegate `Field` to a specialized library because one cannot retroactively conform `FloatingPoint` to `Field`.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
&gt; On Sun, Jan 15, 2017 at 09:14 Dave Abrahams via swift-evolution &lt;<br>
&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt; on Sun Jan 15 2017, Anton Zhilin &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt;&gt; What about taking a mathematical approach to numbers?<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; protocol Group : Equatable {<br>
&gt;<br>
&gt;&gt;     static var zero: Self { get }<br>
&gt;<br>
&gt;&gt;     static func + (Self, Self) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func += (inout Self, Self)<br>
&gt;<br>
&gt;&gt;     static func - (Self, Self) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func -= (inout Self, Self)<br>
&gt;<br>
&gt;&gt;     static prefix func - (Self) -&gt; Self<br>
&gt;<br>
&gt;&gt; }<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; protocol Ring : Group {<br>
&gt;<br>
&gt;&gt;     static var one: Self { get }<br>
&gt;<br>
&gt;&gt;     static func * (Self, Self) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func *= (inout Self, Self)<br>
&gt;<br>
&gt;&gt;     func tryDivide(by: Self) -&gt; Self?<br>
&gt;<br>
&gt;&gt;     func tryInvert() -&gt; Self?<br>
&gt;<br>
&gt;&gt; }<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; protocol Field : Ring {<br>
&gt;<br>
&gt;&gt;     static func / (Self, Self) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func /= (inout Self, Self)<br>
&gt;<br>
&gt;&gt;     var inverted: Self { get }<br>
&gt;<br>
&gt;&gt; }<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; protocol VectorSpace : Group {<br>
&gt;<br>
&gt;&gt;     associatedtype Scalar : Field<br>
&gt;<br>
&gt;&gt;     static func * (Self, Scalar) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func *= (inout Self, Scalar) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func / (Self, Scalar) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func /= (inout Self, Scalar) -&gt; Self<br>
&gt;<br>
&gt;&gt;     static func * (Scalar, Self) -&gt; Self<br>
&gt;<br>
&gt;&gt; }<br>
&gt;<br>
&gt; The first test for the inclusion of any protocol in the standard library<br>
&gt;<br>
&gt; is: “what generic algorithm that uses this protocol as a constraint<br>
&gt;<br>
&gt; would be appropriate for inclusion in the standard library?”<br>
&gt;<br>
&gt; I don&#39;t think we have a use for any of the above directly in the<br>
&gt;<br>
&gt; standard library.  All the generic algorithms I know of that would be<br>
&gt;<br>
&gt; appropriate to those protocols are part of some specialized domain that<br>
&gt;<br>
&gt; should have its own library built on top of the Swift standard lib.<br>
&gt;<br>
&gt;&gt; Detalization of mathematical terminology will be determined by what kind<br>
&gt; of<br>
&gt;<br>
&gt;&gt; types we have in the standard library. Integer types are rings (except for<br>
&gt;<br>
&gt;&gt; overflow), floating-point types are fields (except for precision), point<br>
&gt;<br>
&gt;&gt; types are linear spaces, so I thought the abstractions above are the bare<br>
&gt;<br>
&gt;&gt; minimum.<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; Unfortunately, Swift doesn’t have rename operations for protocol<br>
&gt;<br>
&gt;&gt; requirements, so we can’t express groups that use operations other than +<br>
&gt;<br>
&gt;&gt; and -. What we can do is to include an adapter to wrap current instance in<br>
&gt;<br>
&gt;&gt; an additive group interface:<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; struct MultiplicativeGroupAdapter&lt;T: Field&gt; : Group {<br>
&gt;<br>
&gt;&gt;     // ...<br>
&gt;<br>
&gt;&gt; }<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; extension Field {<br>
&gt;<br>
&gt;&gt;     var multiplicativeGroup: MultiplicativeGroupAdapter&lt;<wbr>Self&gt;<br>
&gt;<br>
&gt;&gt; }<br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;&gt; ​<br>
&gt;<br>
&gt;&gt; ______________________________<wbr>_________________<br>
&gt;<br>
&gt;&gt; swift-evolution mailing list<br>
&gt;<br>
&gt;&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;<br>
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt; --<br>
&gt;<br>
&gt; -Dave<br>
&gt;<br>
&gt; ______________________________<wbr>_________________<br>
&gt;<br>
&gt; swift-evolution mailing list<br>
&gt;<br>
&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;<br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
&gt; ______________________________<wbr>_________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
&gt;<br>
<br>
--<br>
-Dave<br>
<br>
______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
</div></div></blockquote></div><br></div></div>