Chris J Harris
Chris J Harris

Reputation: 1851

Why is the compiler not using Numeric.plus in this case?

I am getting some (what seems to me) strange behavior when using the + method in a generic case class (below). The bottom method works fine, but the top one gives me an error for addVal - type mismatch; found: DataT, required: String.

I assume what is going on here is the compiler has converted this.datum into a String and so wants to use the String.plus method, whereas I want it to use the Numeric.plus method. Normally it would default to using the Numeric.plus method when presented with two Numeric instances so I'm not quite sure why it isn't in this case.

case class SingleValue[DataT <: Numeric[DataT]] (
    datum: DataT,
    ) {
  def addToDatumDoesntWork(addVal: DataT): SingleValue[DataT] = SingleValue[DataT](this.datum + addVal)
  def addToDatumWorks(addVal: DataT): SingleValue[DataT] = SingleValue[DataT](this.datum.plus(this.datum, addVal))
}

Upvotes: 0

Views: 37

Answers (1)

jwvh
jwvh

Reputation: 51271

You're not invoking the Numeric type class the way it was intended.

case class SingleValue[DataT : Numeric](datum: DataT) {
  import Numeric.Implicits._
  
  def addToDatumNowItWorks(addVal: DataT): SingleValue[DataT] = 
    SingleValue[DataT](this.datum + addVal)
}

It can also be done this way. (The two are roughly equivalent.)

case class SngleValue[DataT](datum: DataT)(implicit ev :Numeric[DataT]) {
  import ev._

  def addToDatumNowItWorks(addVal: DataT): SingleValue[DataT] =
    SingleValue[DataT](this.datum + addVal)
  // or
  def addToDatumWorks(addVal: DataT): SingleValue[DataT] =
    SingleValue[DataT](ev.plus(this.datum, addVal))
}

The idea is that you pull in the "evidence" that the proper implicit exists, then you can import what's needed for the infix notation.

Upvotes: 3

Related Questions