I've tried this line of code
def **[A <% Numeric[A]](l:开发者_运维技巧List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2})
However on compilation, I get this error
error: value * is not a member of type parameter A
def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2})
When I look at the source for the Numeric trait, I see a *
op defined.
What am I doing wrong?
The instance of Numeric
is not a number itself, but it is an object that offers operations to do the arithmetic. For example, an object num
of type Numeric[Int]
can add two integers like this: num.plus(3, 5)
The result of this operation is the integer 7.
For integers, this is very trivial. However, for all basic numerical types, there is one implicit instance of Numeric
available. And if you define your own numeric types, you can provide one.
Therefore, you should leave the bounds for A
open and add an implicit parameter of type Numeric[A]
, with which you do the calculations. Like this:
def **[A](l:List[A],m:List[A])(implicit num:Numeric[A])=l.zip(m).map({t=>num.times(t._1, t._2)})
Of course, num.times(a,b)
looks less elegant than a*b
. In most of the cases, one can live with that. However, you can wrap the value a
in an object of type Ops
that supports operators, like this:
// given are: num:Numeric[A], a:A and b:A
val a_ops = num.mkNumericOps(a)
val product = a_ops * b
Since the method mkNumericOps
is declared implicit
, you can also import it and use it implicitly:
// given are: num:Numeric[A], a:A and b:A
import num._
val product = a * b
You can also solve this with a context bound. Using the context
method from this answer, you can write:
def **[A : Numeric](l:List[A],m:List[A]) =
l zip m map { t => context[A]().times(t._1, t._2) }
or
def **[A : Numeric](l:List[A],m:List[A]) = {
val num = context[A]()
import num._
l zip m map { t => t._1 * t._2 }
}
精彩评论