Search code examples
scalaimplicit-conversionimplicit

How to take advantage of mkNumericOps in Scala?


I'm trying to define a new type that can behave essentially like a number (for concreteness, let's say a Double). I'd like to overload operators on this type and I could do this explicitly, but to avoid repetition, I would like to advantage of the methods in NumericOps, which are defined in terms of the abstract methods in Numeric. My understanding is I should be able to just override the methods in Numeric and get the others for free.

Here's the simplest attempt I can think of:

class Container(val value: Double) extends Numeric[Container] {
  override def plus(x: Container, y: Container): Container =
    new Container(x.value + y.value)

  // override minus, times, etc.

  override def toString: String = value.toString
}

println(new Container(1) + new Container(1))

However, this gives me a type mismatch error.

My understanding of implicits is still quite shaky, but I would have thought the implicit def mkNumericOps(lhs: Container): NumericOps inherited by Container would save the day by implicitly converting the two Container objects being added to NumericOps objects and then adding them using the + method defined in terms of Container.plus.

What am I getting wrong here and how can I fix this?


Solution

  • Here is an example to supplement Luis' typeclass comment

    final case class Container(value: Double)
    
    object Container {
      implicit val containerNumeric: Numeric[Container] = new Numeric[Container] {
        override def plus(x: Container, y: Container) = Container(x.value + y.value)
        override def minus...
      }
    }
    
    import Numeric.Implicits._
    Container(1) + Container(1)
    

    which outputs

    res0: Container = Container(2.0)
    

    The import provides infixNumericOps which compiler uses to automatically rewrite to

    infixNumericOps(Container(1)) + Container(1)