General question: What is the proper way to define a generic class typed with a type which is Numeric
, ideally without using any implicit
in Scala 2?
Specific example: consider the following toy class which is built around Integer sequence:
class NewList(val values: Seq[Int]) {
def (x: Int): NewList = new NewList(values.map(_ x))
}
val x = new NewList(List(1,2,3))
(x 5).values // ---> List(6, 7, 8)
Now suppose we want to make NewList
generic, wrapping around any numeric sequence:
// Would not compile
class NewList[T: Numeric](val values: Seq[T]) {
def (x: T): NewList = new NewList(values.map(_ x))
}
The code above would not compile due to some weird type mismatch
cmd2.sc:2: type mismatch;
found : T
required: String
def (x: T): NewList[T] = new NewList(values.map(_ x))
^Compilation Failed
Compilation Failed
As far as I understand, this compilation error apparently means, that compiler could not resolve variable x: T
to be of a Numeric
type, and thus could not resolve type of arguments of plus
. Trying to declare (x: Numeric[T])
or using (implicit num: T => Numeric[T])
either in class definition or method definition would not help.
The only way to make the class compile and behave as expected is to use plus
method of implicitly[Numeric[T]]
:
class NewList[T: Numeric](val values: Seq[T]) {
def (x: T): NewList[T] = new NewList(values.map(implicitly[Numeric[T]].plus(_, x)))
}
val x = new NewList(List(1,2,3))
(x 5).values // ---> List(6, 7, 8)
- Why couldn't compiler resolve method
plus
forT
, even though it is declared asNumeric
in the class definition? - Is there any better way to solve this issue without use of ugly boilerplate
implicitly[Numeric[T]].plus
? - Could we, in general, avoid
implicit
's to handle such cases in scala?
CodePudding user response:
Why couldn't compiler resolve method plus for T, even though it is declared as Numeric in the class definition?
First, because T
IS NOT a Numeric
; rather it has an instance of Numeric
typeclass associated with it
Second, even if T
would be a Numeric
, it would not have a
method; because, again, that is not how typeclasses work.
Check this: https://gist.github.com/BalmungSan/c19557030181c0dc36533f3de7d7abf4
Is there any better way to solve this issue without use of ugly boilerplate implicitly[Numeric[T]].plus?
Yes, just import the extension methods: import Numeric.Implicits._
either at the top level or inside the class
or the method.
Could we, in general, avoid implicit's to handle such cases in scala?
[T: Numeric]
is just sugar syntax for (implicit ev: Numeric[T])
so no, you can't avoid implicits
Which is fine, really.