Why do I have to import Ordering.Implicits?

Viewed 165

In he code below I get a compilation error unless I import Ordering.Implicits. Why is that import necessary? Is there a way around that? Am I doing something completely off-base?

Error:(15, 38) value < is not a member of type parameter A
      case (ah :: as, bh :: _) if ah < bh => findOverlap(c, as, b)
  private def foo[A : Ordering](c: mutable.Set[A], a: Seq[A], b: Seq[A]): mutable.Set[A] =
    (a, b) match {
      case (ah :: _, bh :: _) if ah == bh => c + ah
      case (ah :: as, bh :: _) if ah < bh => foo(c, as, b)
      case (_, _ :: bs) => foo(c, a, bs)
    }
2 Answers

The < method comes from an inner class Ops of the Ordering trait. There's an implicit conversion inside Ordering that provides it, but just having an implicit instance of Ordering isn't enough for that to be in scope. You can import it explicitly:

  val ordering = implicitly[Ordering[A]]
  import ordering.mkOrderingOps

...or you can import Ordering.Implicits, which contains a few utility methods for handling Ordering. One of them is an implicit conversion which provides an Ops instance whenever you have an Ordering in scope.

The reason why you need to import Ordering.Implicits is usage of boolean operations like <, > and so on.

By importing it, you tell compiler to use scala.math.Ordering.Ops

  class Ops(lhs: T) {
    def <(rhs: T) = lt(lhs, rhs)
    def <=(rhs: T) = lteq(lhs, rhs)
    def >(rhs: T) = gt(lhs, rhs)
    def >=(rhs: T) = gteq(lhs, rhs)
    def equiv(rhs: T) = Ordering.this.equiv(lhs, rhs)
    def max(rhs: T): T = Ordering.this.max(lhs, rhs)
    def min(rhs: T): T = Ordering.this.min(lhs, rhs)
  }

allowing you to call < on type A

Related