Scala has a number of traits that you can use as type classes, for example Ordered and Numeric in the package scala.math.
I can, for example, write a generic method using Ordered like this:
def f[T <% Ordered[T]](a: T, b: T) = if (a < b) a else b
I wanted to do a similar thing with Numeric, but this doesn’t work:
def g[T <% Numeric[T]](a: T, b: T) = a * b
Why is there an apparent discrepancy between Ordered and Numeric?
I know there are other ways to do this, the following will work (uses a context bound):
def g[T : Numeric](a: T, b: T) = implicitly[Numeric[T]].times(a, b)
But that looks more complicated than just being able to use * to multiply two numbers. Why does the Numeric trait not include methods like *, while Ordered does include methods like <?
I know there’s also Ordering which you can use in the same way as Numeric, see also this answer:
def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)
Orderedis just a few simple pimped methods that return eitherIntorBoolean, so no type-trickery is needed.Numeric, on the other hand, has methods that return different types depending on the exact subclass used. So whileOrderedis little more than a marker trait,Numericis a fully-featured type class.To get your operators back, you can use
mkNumericOps(defined inNumeric) on the lhs operand.UPDATE
Miles is quite right,
mkNumericOpsis implicit, so just importing that instance of Numeric will give you back all the magic…