Exponent for fractional and/or numeric type classe(s)

In my opinion, the Fractional and/or Numeric type-classes lack one feature that I personally end up recoding a lot: being able to exponentiate by an integer.

Current situation
Currently, only the math package has the function pow, acting only on Doubles. But any group can be equipped with integer exponentiation, and any monoid with non negative integer exponentiation. Of course, in the case of Numeric and Fractional, exponentiation is naturally associated with the “times” and “div” (for the latter) methods. This, for the case of Numeric, leaves a question mark: should a negative exponentiation of a numeric return 0, or raise an exception?

Adding a numericPow and a fractionalPow to both of these type classes.

I would use ** since ^ is already taken, and it is consistent with some other languages, such as python.

To be discussed
What should a negative exponentiation on numeric give? And perhaps the symbol…

Simply defining the two afore mentioned functions in the math package, asking for implicit Numeric or Fractional, so something like def numericPow[A: Numeric](base: A, exponent: Int): A = ???

I don’t understand. Why not just Numeric pow and Fractional override pow for the negative case ?

I would go for raise an exception.

It has wrong precedence, same as *. In addition, we need a right associative operator. In my project https://github/com/rjolly/scas I use a \: symbol. The project https://github.com/PoslavskySV/rings is happy with the literal method x.pow(y).

In that case you do need two distinct methods for numeric/integral and fractional, so adding a default method in the type classes sounds better.

I might be wrong but I don’t think it’s a good idea to override methods for type classes. Because you could be caught off guard by using your methods, thinking you have a fractional in scope, whereas you only have a numeric in scope. But maybe I have too much concern.

Indeed, it’s a pity… I’m also not against having to write x.pow(y). \: seems really weird to me :smiley:

I agree.

As per https://github.com/scala/scala-dev/issues/661 , we can’t add stuff to the standard library at the moment.

Consider using a third-party package such as Spire.

I would add that it’s somewhat unclear what Numeric's ambition level is or should be. I want to say that Numeric doesn’t aim to provide all the math operations one might want. It exists to support operations such as .sum and .product. It doesn’t have bigger ambitions than that. But it’s not really that simple, because there are things in Numeric that don’t really need to be there afaict. I suspect that back when Numeric was introduced, it was unclear what the eventual ambition level might end up being.

So I have heard, but it can still be discussed for later :slight_smile:

I understand your point about the goal (ambition) of the numeric type class, and I guess it makes sense. I still think it’s a pity to have to load an entire library (thanks for reminding me of Spire by the way, that’s a library I could feel comfortable contributing to :D) only to do such a basic operation as exponentiate numbers…

I’m perhaps actually dreaming of another kind of type class :thinking:


I suggest something similar in Proposal: new operator for exponentiation

I took the liberty to make a PR at https://github.com/scala/scala/pull/9093

FWIW, it’s easy to add this as extension method through a library.

E.g. in Numbers, I use 2 pow 3 (this gives Double but you could add a case for integers or longs)