I would like to generalize the Vector class to add some basic math features. I have done this for Vector[Scalar] (based on my Scalar class), a portion of which is shown below. How can I generalize this to also work for Vector[Int] and Vector[Double] without repeating the whole implementation? I am using Scala 3. Thanks.

Iâ€™d still like to know how to generalize this implicit class to handle any numeric type that has basic mathematical operators such as +, -, *, /, etc. When I try to generalize it as

implicit class Vectorx[A](self: Vector[A]):

the compiler tells me that type A does not support those operators. I looked for a trait, but there does not seem to be one. Is there a way to limit the type of A to a discrete set of types, such as Int, Long, Float, Double, etc.? I am using Scala 3. Thanks.

You could specify a subtype for each primitive numeric type, and maybe one for BigInt. There arenâ€™t that many, and maybe you donâ€™t need them all? Maybe Double and Long or BigInt is all you need?

I used to think, in the past, that there should be a trait Number, which provides basic math operators, and from which all primitive numbers inherit.

I have since changed my mind, since the practical use of such a super-type is very limited.

Although all the numbers have basic math, they behave differently. Division by zero throws an exception for integers, but returns a special value for floating points. And 3/2 is very different from 3.0/2.0.

Overflow is different. Integers wrap around, while floating points result in special values.

So, whatâ€™s left? Matrix multiplication can be written the same for integers and floating points, but for integers, you can run into overflows very quickly, so maybe you will need a BigInt anyway? For more serious linear algebra, like matrix inversion or finding eigenvalues, I donâ€™t think one can use the same algorithm for integers as for floating points.

So, you can try to generalize over all primitive numeric types, but it may be a lot of work for relatively little gain.

Thanks for the reply. The generalized numeric Vector is not something I really need. I was really just curious about it and wondering if I was missing some simple little trick.

Iâ€™m not sure what you mean by â€śspecify a subtype for each primitive numeric type.â€ť Can you elaborate on that? You are right that I donâ€™t need very many. Iâ€™d settle for Int, Long, Bigint, Float, Double, and perhaps BigDecimal.

If you really want this, in spite of the drawbacks and limitations @curoli has listed, @BalmungSanâ€™s advice sounds just right. Based on Numeric (in Scala 2):

I was hoping somebody would bring up Numeric so I wouldnâ€™t have to

A few caveats about Numeric:

It wasnâ€™t created as a full-on effort to really fully support abstracting across numeric types. Itâ€™s more a minimal thing that was made to support collections methods such as .sum, .product, and .mean. So it has basic stuff but depending on what youâ€™re doing you may hit a wall.

In high-performance contexts where youâ€™re crunching tons of data and every cycle and every byte counts, routing operations through the typeclass might be unacceptable performancewise. Of course in many applications it doesnâ€™t matter at all.

Uh, maybe? Not sure if anybody has benchmarked that. I probably should have used some more cautious wording like â€śconsider a possible performance impact, dependingâ€ť. Would love to learn that I was too pessimistic on this point.