Во-первых, я думаю, что причиной переполнения вашего стека является использование [A <: Comparable[_]]
.Экзистенциальный тип на практике означает, что на самом деле вы не можете сравнить A
ни с чем.Это означает, что компилятор «выбирает» неявное преобразование для повторного вызова в вызове self.compareTo
(отсюда и рекурсия).Вы бы увидели это, если бы использовали переключатель компилятора -XprintTypes
Так что же делать?
Рассмотрим разницу между Ordering
и Ordered
.Должен быть неявный порядок для вашего типа.
implicit def comp2ord[A <: Comparable[A]] = new Ordering[A] {
def compare(x : A, y : A) = x compareTo y
}
И затем способ превратить этот порядок в Ordered
:
implicit def ordering2order[A : Ordering](x : A) = new Ordered[A] {
def compare(y : A) = implicitly[Ordering[A]].compare(x, y)
}
Использование без неявного упорядочения:
scala> val df = new java.text.SimpleDateFormat("yyyy-MM-dd")
df: java.text.SimpleDateFormat = java.text.SimpleDateFormat@f67a0200
scala> TreeSet(df.parse("2011-03-04"), df.parse("2010-05-06"))
<console>:13: error: could not find implicit value for parameter ord: Ordering[java.util.Date]
TreeSet(df.parse("2011-03-04"), df.parse("2010-05-06"))
^
Теперь с неявным порядком ...
scala> implicit def comp2ord[A <: Comparable[A]] = new Ordering[A] {
| def compare(x : A, y : A) = x compareTo y
| }
comp2ord: [A <: java.lang.Comparable[A]]java.lang.Object with Ordering[A]
scala> TreeSet(df.parse("2011-03-04"), df.parse("2010-05-06"))
res1: scala.collection.immutable.TreeSet[java.util.Date] = TreeSet(Fri Mar 04 00:00:00 GMT 2011, Thu May 06 00:00:00 BST 2010)
Конечно, вам также потребуется неявное преобразование из Ordering
в Ordered
чтобы воспользоваться сравнениями scala с помощью <
, >=
и т. д .:
scala> implicit def ordering2order[A : Ordering](x : A) = new Ordered[A] {
| def compare(y : A) = implicitly[Ordering[A]].compare(x, y)
| }
ordering2order: [A](a: A)(implicit evidence$1: Ordering[A])java.lang.Object with Ordered[A]
scala> df.parse("2010-04-05") < df.parse("2009-01-01")
res2: Boolean = false
В случае, если ваш тип A
является классом Java, который реализует raw-type Comparable
, вам нужно будет предоставить явное преобразование:
implicit def comp2ord(x : DateTime) = new Ordered[DateTime] {
def compare(y : DateTime) = x compareTo y
}