Search code examples
scalaimplicit-conversion

Generic Point Addition in Scala


I'm trying to pimp the Tuple(2) class with addition and scala multiplication members, so that I can use them more easily as geometric 2D points. This is what I've got:

implicit class Point[+T: Numeric](val t: (T, T)) {
  import Numeric.Implicits._
  def _1 = t._1
  def _2 = t._2

  def +[V >: T](p: Point[V])(implicit ev: Numeric[V]) : (V,V) = 
    (ev.plus(t._1, p._1), ev.plus(t._2, p._2))
}

println((2, 3) + Point(5.0, 6.0))

This doesn't work (can't find ev) presumably because strictly speaking Float isn't a supertype of Int - but there doesn't actually seem to be a weak-conformance-bound operator, and leaving it out entirely means I can't use ev.plus anymore because it's expecting two values of the same type V, not one of T and one of V.

How can I properly implement this code?


Solution

  • You are absolutely right. The problem is that Numeric[T] doesn't allow one to mix types (V and T) according to it's signature: def plus(x: T, y: T): T.

    You can either use/emulate this library: https://github.com/azavea/numeric. It does a lot of implicit gymnastics to allow mixed types to work.

    It does exactly what you need:

    EasyImplicits allows you to operate on mixed numeric types (e.g. T + U + Int).

    Alternatively chose to use underlying Double type instead of T/V - I know that's not always great (loss of precision, etc).

    You code still works with points that don't mix types which is not that bad, otherwise Double doesn't look that terrible since automatic conversion will happen anyway.