<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Overall I agree with the direction that while we should be _inspired
    by_ algebraic structures, we should not slavishly adhere to them,
    because these are not platonic numbers, and they fail to obey the
    algebraic axioms in all sorts of ways.  <br>
    <br>
    I think we can borrow much hard-won experience from our friends in
    the Haskell community.  For example, `Num a` defines both (+) and
    (*), and suggests the existence of additive and multiplicative
    identities, but appeals not to ring-ness but to something more like
    "be reasonable".  Specifically, it says "looks like a ring, lots of
    Nums are rings, but actually requiring it would be too
    restrictive."  And despite the seeming complexity of the Haskell
    numeric tower, there is much (sensible) lumping going on in the base
    Num class.  (All of these properties seem like candidates for
    shameless stealing.)<br>
    <br>
    Haskell also relegates the algebraic structure (ring, monoid, etc)
    to a different corner of the field (heh), separate from the types
    describing numerics, and doesn't attempt to use symbolic operators,
    instead using nominal functions like `mzero`.  <br>
    <br>
    The point about implementing both `Num` and `Ord` is one of those
    "obvious not obvious" statements; given that an ordered ring
    includes additional axioms above the union of the ring and ordering
    axioms, it would not be reasonable to expect "witnesses Ord" and
    "witnesses Ring" to mean "witnesses OrderedRing".  Instead, one
    would need an OrderedRing type class, which extends Ord and Eq, and
    adds additional laws.  <br>
    <br>
    <blockquote type="cite">
      <p>The Haskell Report defines no laws for <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#t:Num" title="GHC.Num">Num</a></code>. However, <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-43-" title="GHC.Num">+</a></code>)</code> and <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-42-" title="GHC.Num">*</a></code>)</code> are customarily
        expected to define a ring and have the following properties:</p>
      <dl>
        <dt><strong>Associativity of <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-43-" title="GHC.Num">+</a></code>)</code></strong></dt>
        <dd><code class="inline-code">(x + y) + z</code> = <code class="inline-code">x + (y + z)</code></dd>
        <dt><strong>Commutativity of <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-43-" title="GHC.Num">+</a></code>)</code></strong></dt>
        <dd><code class="inline-code">x + y</code> = <code class="inline-code">y + x</code></dd>
        <dt><strong><code class="inline-code"><code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:fromInteger" title="GHC.Num">fromInteger</a></code> 0</code> is the
            additive identity</strong></dt>
        <dd><code class="inline-code">x + fromInteger 0</code> = <code class="inline-code">x</code></dd>
        <dt><strong><code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:negate" title="GHC.Num">negate</a></code> gives the additive
            inverse</strong></dt>
        <dd><code class="inline-code">x + negate x</code> = <code class="inline-code">fromInteger 0</code></dd>
        <dt><strong>Associativity of <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-42-" title="GHC.Num">*</a></code>)</code></strong></dt>
        <dd><code class="inline-code">(x * y) * z</code> = <code class="inline-code">x * (y * z)</code></dd>
        <dt><strong><code class="inline-code"><code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:fromInteger" title="GHC.Num">fromInteger</a></code> 1</code> is the
            multiplicative identity</strong></dt>
        <dd><code class="inline-code">x * fromInteger 1</code> = <code class="inline-code">x</code> and <code class="inline-code">fromInteger
            1 * x</code> = <code class="inline-code">x</code></dd>
        <dt><strong>Distributivity of <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-42-" title="GHC.Num">*</a></code>)</code> with respect to <code class="inline-code">(<code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:-43-" title="GHC.Num">+</a></code>)</code></strong></dt>
        <dd><code class="inline-code">a * (b + c)</code> = <code class="inline-code">(a * b) + (a * c)</code> and <code class="inline-code">(b + c) * a</code> = <code class="inline-code">(b * a) + (c * a)</code></dd>
        <dt><strong>Coherence with <code class="inline-code">toInteger</code></strong></dt>
        <dd>if the type also implements <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Real.html#v:Integral" title="GHC.Real">Integral</a></code>, then <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#v:fromInteger" title="GHC.Num">fromInteger</a></code> is a left inverse
          for <code><a href="https://hackage-content.haskell.org/package/ghc-internal-9.1401.0/docs/GHC-Internal-Real.html#v:toInteger" title="GHC.Internal.Real">toInteger</a></code>, i.e. <code class="inline-code">fromInteger (toInteger i) == i</code></dd>
      </dl>
      <p>Note that it <em>isn't</em> customarily expected that a type
        instance of both <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/GHC-Num.html#t:Num" title="GHC.Num">Num</a></code> and <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Data-Ord.html#t:Ord" title="Data.Ord">Ord</a></code> implement an ordered ring.
        Indeed, in <code class="inline-code">base</code> only <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Prelude.html#t:Integer" title="Prelude">Integer</a></code> and <code><a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Data-Ratio.html#v:Rational" title="Data.Ratio">Rational</a></code> do.</p>
    </blockquote>
    <br>
    <br>
    <br>
    <br>
    <blockquote type="cite" cite="mid:qlqc1xq5SxJ78QoSOZJQIOYVJWN07RS3rnts6DIBM_k=.477be243-b55c-4808-89d2-2db13ced3439@github.com">
      <pre wrap="" class="moz-quote-pre">One of the implicit design question here is "are these the interfaces that allow operator overloading?" or "are these the interfaces that declare various algebraic properties?"

Since many of the numerical types of possible interest are closer to, say, floating-point-like types that have few algebraic properties rather than integer-like types that have more, I don't want to preclude floating-point-like types from participating in operator overloading because of their lack of strong algebraic properties. Matrices/vectors would also fall closer to floating-point-like rather than integer-like and I would not want to preclude matrices/vectors from benefiting from operators.

I included a slide in my 2025 JVMLS talk on numerics speculating that a future refinement of these kinds of interfaces could include an idiom to indicate "yes, this type actually obeys the ring axioms" or "... the field axioms", etc., but that is not included in this early "lumpy" iteration.

I would fully expect some evolution of the set of interfaces, what methods go where, the set of interfaces, etc. as we can more experience using these trial types with type classes.

Thanks.

-------------

PR Review Comment: <a class="moz-txt-link-freetext" href="https://git.openjdk.org/valhalla/pull/1917#discussion_r2700497372">https://git.openjdk.org/valhalla/pull/1917#discussion_r2700497372</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>