Ben Sidhom
Ben Sidhom

Reputation: 1588

Implicit conversion from TupleN to Comparable

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)

Upvotes: 1

Views: 849

Answers (1)

J Cracknell
J Cracknell

Reputation: 3547

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)
}

Upvotes: 1

Related Questions