1

I'm trying to use Scala tuples in a Java collection library that requires its elements to be Comparable. I know that recent versions of Scala allow lexicographical ordering of tuples through math.Ordering.Implicits. However, it looks like there exists no default conversion from Scala's Ordering[T] to Java's Comparable[T]. Whether or not I've imported tuple orderings, I get the error java.lang.ClassCastException: scala.Tuple2 cannot be cast to java.lang.Comparable.

Is there a way to automatically convert an Ordered or Ordering type to Comparable? If not, is it possible to more specifically make tuples Comparable in a lexicographical fashion? I'm looking for something better than creating a custom case class that implements Comparable for more generality and to reduce boiler-plate and typographical noise ((a, b, c) is much cleaner and easier to type than BeanLikeClassWithComparable(a, b, c)).

EDIT: I've attempted to use J Cracknell's solution, but to no avail (I receive the same error as above). I've posted an attempted implementation of the Wrapped class; it's a less general implementation for pairs and doesn't seem to work.

import scala.math.Ordering.Implicits._

case class OrderedPair[A <: Ordered[A], B <: Ordered[B]](elem: (A, B)) 
  extends Ordered[OrderedPair[A, B]] {
  override def compare(that: OrderedPair[A, B]): Int = 
    implicitly[Ordering[(A, B)]].compare(this.elem, that.elem)
}

implicit def tuple2ToOrdered[A <: Ordered[A], B <: Ordered[B]](x: (A, B)) = OrderedPair(x)
Community
  • 1
  • 1
Ben Sidhom
  • 1,548
  • 16
  • 25

1 Answers1

1

Any type A for which there exists an implicit Ordering[A] is implicitly convertible to Ordered[A] <: Comparable[A] provided scala.math.Ordered is in scope for implicit conversion. Unfortunately the underlying value is lost during the conversion, so I doubt this fulfills your needs.

If you want to proceed using scala's orderings, you will most likely need to create a data structure to capture both the subject and its implicit ordering:

case class Wrapped[A](elem: A)(implicit ordering: Ordering[A])
  extends Ordered[Wrapped[A]]
{
  def compare(that: Wrapped[A]): Int = ordering.compare(this.elem, that.elem)
}
J Cracknell
  • 3,498
  • 1
  • 19
  • 13
  • Thanks. I'm not sure exactly what this means for values that might actually be stored in the collection, since they would be wrapped before insertion. It also seems not to work (see the edit above). – Ben Sidhom Oct 23 '13 at 00:51
  • How are you typing your collection? It would need to be `Coll[Wrapped[A]]`, the idea being that `Wrapped[A]` implements `Comparable` while still providing a reference to the stored `A` (in your case a tuple). – J Cracknell Oct 23 '13 at 01:42