Splitting Numeric to separate Sum from Product

The scala.math.Numeric typeclass defines addition and multiplication
operations together in one non-separable interface. There are
reasonably common situations where an addition operation can be
defined without a multiplication operator for "Number-like" data:

- (Mathematical) vectors of the same dimension can be added, but not
in general multiplied to produce another vector.
- Multiplication of matrices of the same dimension is not always defined.

Would there be any problem in factoring out two super-trait
typeclasses above Numeric, enabling addition and multiplication to be
defined separately?

I for one would find this useful. For example, one could define
TraversableOnce.{sum, product} in terms of their more specific
operations, and sum a collection of vectors component-wise.

-Ben

Re: Splitting Numeric to separate Sum from Product

On Fri, Sep 9, 2011 at 11:07 PM, Erik Osheim <erik [at] plastic-idolatry [dot] com> wrote:
If this is a big concern of yours then you'd probably want to go the
way Python has and have two division operators: floor division and true
division.
Or possible just return a reminder with the floor.

I don't consider removing integer division to be a useful way to
resolve this issue.
Remove/rename I'm not suggesting making the operation unavailable, just to make it harder to accidentally use it.

It seems like you are saying that we need to cripple integral types and
slow down the fractional types in order to satisfy "enterprise
programmers," even though these same souls are already working with
Java and C#, both of which have these exact same issues. Am I
misunderstanding?
No you understand me correct. Yes they are struggling with these issues in Java and C#, and Scala are in many way positioning it self as an improvement over the current mainstream languages. I'm just proposing that it could be even more of an improvement.

Compare it to null vs Option[T], yes you are constructing and boxing your values which have a performance impact. But in the end the common case is "fast enough" to warrant its use.

I'm not convinced that you have to "cripple" anything or make scientific computing impossible to achieve this though. Btw. there are chips out there that have hardware implementation of the decimal floats, would the feature be readily available in mainstream languages I'm sure Intel and AMD would include it it into their chips.

BR,
John

Re: Splitting Numeric to separate Sum from Product

Well, you have met at least one person (me). The main thing is that while double and int both define a "division" operator, they are not the same thing, and I honestly haven't run into the case where I wouldn't want to separate the 2 (though I assume you and I are working on fairly different projects).
I actually like the separation of Numeric and Fractional (keep in mind, Fractional inherits from Numeric). I use it these extensively in a geometry library I developed and its nice that when you see a function that only requires Numeric, as you know your answers will be exact with BigDecimal or Ints. When you see a Fractional requirement, you know you need to use Rational numbers to achieve an exact result. You could also use Double or BigDecimal, but then the results are not guaranteed to be exact. Since all my geometric objects are abstracted over the number type, being able to know what operations you can apply to them is nice.
In this library, many predicates and orderings can be defined using only addition & multiplication. For instance, I define an intersection ordering for pairs of lines. This ordering doesn't require division, but this would not be immediately obvious to someone seeing this for the first time, since finding and reporting the intersection DOES require division (unless you are using homogeneous coordinates). Having only a Numeric implicit required is a reassurance to a user of the library, since it means the ordering is correctly defined and exact for lines using Int, BigInt or BigDecimal (this wouldn't be the case if division were used).
The separation is also necessary for ints (I think), as integer division (in Scala) is not real division. I wouldn't want someone thinking they could use an Int when it will give an unknown/incorrect (as opposed to inaccurate) result. And, as noted above, it is nice to be able to see the wide range of operations available to you if you use Int (or BigInt), which may not always be obvious.

Re: Splitting Numeric to separate Sum from Product

Hi Tom,

Thanks for your thoughtful reply and description of your use case. I'm
sorry if I came off as hostile but I couldn't tell if you actually
needed the current Numeric behavior or were just playing devil's
advocate.

First of all, is your library online? I have been working on my own
classes for complex and rational numbers and would love to see what
you've come up with. And please feel free to give me feedback on my own
Numeric project.

It does sound like our cases are different. In one of my cases, I am
dealing with large (e.g. 100M cells) grid of numbers (could be 64-bit
floating point, 32-bit integer, whatever) which represents some kind of
geographical data (e.g. elevation data, soil type, etc). I want to be
able to write operations which work no matter what the underlying data
type is, without having to convert the underlying data type, or
duplicate code.

Operations on this data might include division, for instance when
converting units, rescaling or normalizing data. In these cases,
maintaining exact precision is usually less important since the data is
usually already aggregated/sampled. Instead we are very focused on
performance, since we need to be able to do this processing at
"web-appropriate speeds".

Floor division and true division definitely are different operations,
but I think even the fact that we use the same operator symbol for both
shows that we consider them somewhat analogous. While abstracting
across integral/fractional types may be inappropriate in some contexts,
do you think it's *always* inappropriate and should be forbidden?

I strongly believe there needs to be some way to do this in Scala (as
there is in most dynamically typed languages, e.g. Clojure, Python,
Ruby, etc). Java completely lacks this ability and I think it is a
feather in Scala's cap that it is possible.

I wonder if there isn't a way to achieve the kind of "numeric precision
tracking" which you're doing in a better way, rather than using the
(current) properties of Fractional and Numeric? This could involve
creating additional type classes which group the types according
to which operations they can use while maintaining precision.

I suggest this because everyone has different ideas of how much
precision they need. In my case, I'm willing to be limited to the
precision of the underlying data type. In finance, I think most people
don't need to use Rational (because they don't need infinite precision
on fractions like 1/3, but only as much as they need) and are willing
to consider division on BigDecimal "precise enough". In your case, you
don't want to lose *any* precision. I don't think we can settle this
issue just one way, because everyone has their own requirements.

Re: Splitting Numeric to separate Sum from Product

Hi,

I pretty much have the same problems as everyone wit Numeric here.

An example hereis the work to optimize Range/NumericRange Numeric where
Numeric has largely prevented me on making the "sum" method run in < 1ms
instead of > 35s for "1 to Int.MaxValue".

The bad thing is, that I can't start requiring Integral or Fractional
without breaking the API, which just provides me with a Numeric.

So I pretty much agree that we need a better types dealing with numbers.
Maybe it is possible to get additional people interested in that topic
(e. g. people from Scalala) on the same table, so see if there is common
ground which the standard libraries can provide to help interoperability
between different projects.

Seeing what Anti-XML does Scala devs generally seem to be willing to
break the ABI if people can demonstrate measurable and meaningful
benefits, so maybe there is a chance to get this into 2.11 if a workable
solution is available _before_ 2.10 ships?

Thanks and bye!

Simon

Copyright © 2013 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland