First, let's see their declaration:
implicit def mkNumericOps (lhs: T): IntegralOps
implicit def mkOrderingOps (lhs: T): Ops
The fact that they are implicit means their goal is to provide some automatic value or conversion. Note that they both convert from T
to some other type, where T
is the type parameter of the trait: Integral[T]
.
So, if you have Integral[Int]
, then mkNumericOps
will give you an automatic conversion from Int
to IntegralOps
. That means you'll be able to call methods from IntegralOps
or Ops
on an Int
(or whatever it is the type of your Integral
).
Now, let's see what methods are these:
def % (rhs: T): T
def * (rhs: T): T
def + (rhs: T): T
def - (rhs: T): T
def / (rhs: T): T
def /% (rhs: T): (T, T)
def abs (): T
def signum (): Int
def toDouble (): Double
def toFloat (): Float
def toInt (): Int
def toLong (): Long
def unary_- (): T
These are from IntegralOps
, which extends Ops
. An interesting thing about them is that many of them are already defined on Int
! So, how and why one would use them? Here's an example:
def sum[T](list: List[T])(implicit integral: Integral[T]): T = {
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
So, given any type T
for which there's an Integral[T]
implicitly available, you can pass a list of that type to sum
.
If, on the other hand, I made my method specific for the type Int
, I could write it without Integral
. On the other hand, I can't write something that will work for both Int
and Long
and BigInt
, because they do not share a common ancestor defining the method +
(much less a `zero´).
The foldLeft
above is effectively translated as this:
list.foldLeft(integral.zero)((x, y) => mkNumericOps(x).+(y))