Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch for scala.math.Numeric: splits Arithmetic operations into fine grained traits #5202

Closed
scabug opened this issue Nov 18, 2011 · 2 comments

Comments

@scabug
Copy link

scabug commented Nov 18, 2011

The current scala.math.Numeric is adequate for representing the common integer and decimal number types used on the JVM. However, its a coarse interface that defines alot of operations in a one indivisible trait, and this makes it difficult to generalise or extend to "number-like" entities for which the full Numeric interface is not appropriate, such as non-scalar values.

The proposal, which includes a modified version of the Scala source that implements that change, is to lift out of Numeric four finer-grained traits modelling the arithmetic operations;

  • Additive
  • Subtractive
  • Multiplicative
  • Divisive

Data types can supports a subset of the Numeric operations without needing to support those semantics of Numeric which are problematic for non-scalar data:

  • Total ordering via Ordering
  • Conversion to/from scalar values

Motivating Use Cases

Here are examples of such data for which a total ordering, or conversions to/from scalar values, is not easily defined:

(a) Intervals (ie regions of the number line). Interval/Affine arithmetic defines arithmetic operations over intervals, but not a total ordering [http://en.wikipedia.org/wiki/Interval_arithmetic].

(b) Vectors. While Vectors of like dimension can be added and subtracted, they cannot in general be multiplied using a (Vector, Vector) => Vector operator. They are only partially ordered.

(c) Matrices. Addition is defined for one subset of matrices, while multiplication is defined for another. If matrix dimensions are encoded into their type (eg Matrix[T, _2, _1]), then it is possible to define additive or multiplicative operators where appropriate, and yet be unable to support the full Numeric interface.

Compatibility

The proposed change varies the current API only by lifting the division operator from Fractional/Integral up to Divisive, a super trait of Numeric. This change has been requested by a number of users on the mailing lists [eg recently mentioned in these threads http://www.scala-lang.org/node/10871 http://www.scala-lang.org/node/11392].

Clients code calling Numeric should be unaffected. The division change will break existing implementers of Numeric outside the standard library, but anecdotal evidence suggests there are few of these (I've tried, which led to this patch).

This patch likely break binary compatibility (although Im far from an expert on the matter).

I don't believe it will obstruct specialisation of Numeric typeclasses for the common JVM types to address boxing issues.

Patch

I offer a patch to the standard library which implements this separation in commits:
benhutchison/old-scala-numeric@e7166f6aad25f4ae1ae55
benhutchison/old-scala-numeric@de30205a9e305c2494027

Example code

Shows the integration of the new typeclasses with the collections API:

package example
import math._

object Example extends App {
 implicit val stringAddition = new Additive[String] {
   def zero = ""
     
   def plus(s1: String, s2: String) = s1 + s2 
 }
 
 type complex[T] = (T, T)
 implicit def complexMultiplication[T: Numeric](implicit n: Numeric[T]) = new Multiplicative[complex[T]] {
   import n._
   
   def one = (n.one, n.zero)
   
   def times(z1: complex[T], z2: complex[T]) = {
     val (r1, i1) = z1
     val (r2, i2) = z2
     val real = (r1 * r2) - (i1 * i2)
     val imag = (r1 * i2) + (r2 * i1) 
     (real , imag)
   }
 }
 
 println(Seq("a", "b", "c").sum)
 
 val i = (0.0, 1.0)
 println(Seq(i, i).product)
}

Wisdom from Haskell

Haskell has a Num typeclass that pre-dates Scala. Accordingly, they have more accumulated experience. There's evidence of a similar desire to break up the typeclasses and make the Haskell interfaces more minimal. We should take the opportunity to do this in Scala now, before the weight of existing code makes changes more difficult.

http://osdir.com/ml/libraries@haskell.org/2011-09/msg00009.html
http://www.haskell.org/haskellwiki/Numeric_Prelude
http://repetae.net/recent/out/classalias.html

@scabug
Copy link
Author

scabug commented Nov 18, 2011

@scabug
Copy link
Author

scabug commented May 20, 2012

@retronym said:
I think it is best to let the scala-numeric project mature before considering updating scala.math.Numeric. Please help out Erik and Tom by trying it out and influencing the design.

http://days2012.scala-lang.org/sites/days2012/files/osheim_gennum.pdf
https://github.com/azavea/numeric

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant