Home > Mobile >  Proper way to use Numeric type bounds for classes in scala
Proper way to use Numeric type bounds for classes in scala

Time:04-01

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 for T, even though it is declared as Numeric 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.

  • Related