无法使用隐式转换为Comparable提供从DateTime到Ordered的隐式转换

时间:2011-01-13 07:19:11

标签: scala

我正在尝试使用带有DateTime(joda)的> =,>等等,我能让它工作的唯一方法就是使用这种隐式转换

implicit def dateTime2ordered(x: DateTime): Ordered[DateTime] =
new Ordered[DateTime] with Proxy {
  val self = x

  def compare(y: DateTime): Int = {
    x.compareTo(y)
  }
}

我希望使用更通用的表单,例如

implicit def comparable2ordered[A <: Comparable[A]](x: A): Ordered[A] =
    new Ordered[A] with Proxy {
      val self = x

      def compare(y: A): Int = {
        x.compareTo(y)
      }
    } 

但编译器无法找到此转换,并且在尝试直接调用它之后,我得到以下消息声称DateTime不是Comparable类型[A]。检查DateTime的源代码后,我发现它只将Comparable实现为原始类型。

我能够使用

使其工作
 implicit def comparable2ordered[A <: Comparable[_]](x: A): Ordered[A] =
    new Ordered[A] with Proxy {
      val self = x

      def compare(y: A): Int = {
        x.compareTo(y)
      }
    } 

我的问题是:这是对此问题的正确Scala处理方式,还是通配符类型绑定会导致类型检查的未来问题?

3 个答案:

答案 0 :(得分:7)

我偶然发现了这个问题,因为我也希望使用关系运算符来比较joda DateTime对象。

丹尼尔的回答指出了我正确的方向:scala.math.Ordered中的含义会将A extends java.lang.Comparable[A]的实例转换为Ordered[A] - 它们只需要被纳入范围。最简单的方法(我学习here,顺便说一句)是使用implicitly方法:

val aOrdering = implicitly[Ordering[A]]
import aOrdering._

问题是org.joda.time.DateTime不会扩展或实施Comparable本身,它({间接)从org.joda.time.ReadableInstant继承, 扩展{{1} }}。所以这个:

Comparable

将无法编译,因为val dateTimeOrdering = implicitly[Ordering[DateTime]] import dateTimeOrdering._ 未展开DateTime。要在Comparable[DateTime]上使用Ordered的关系运算符,您必须改为:

DateTime

有效,因为val instantOrdering = implicitly[Ordering[ReadableInstant]] import instantOrdering._ 扩展了ReadableInstantComparable[ReadableInstant]中的隐式转化可以将其转换为Ordered

到目前为止,这么好。但是,有些情况下Ordered[ReadableInstant]不够好。 (我遇到的是ScalaTest的greater and less than Matchers。)为了获得Ordered[ReadableInstant],我被迫这样做:

Ordered[DateTime]

似乎应该有一种更简单的方式,但我无法想出一个。

答案 1 :(得分:3)

很好,原始类型“Comparable”在Scala中被翻译为“Comparable [_]”。

它们被称为存在类型,可比较[_]是“可比较[T] forSome {类型T}”的简写(自2.7版本见http://www.scala-lang.org/node/43

另请参阅http://www.artima.com/scalazine/articles/scalas_type_system.html

中的“存在类型”

答案 2 :(得分:2)

看,事情是,这已经存在。好吧,有点......如果你看一下内部对象Ordered,在那里寻找隐式转换,你会发现:

implicit def orderingToOrdered [T] (x: T)(implicit ord: Ordering[T]) : Ordered[T]

因此,只要有Ordering[T]可用,就可以生成Ordered[T]。现在,要在Ordering[T]对象中查找Ordering

implicit def ordered [A] (implicit arg0: (A) ⇒ Comparable[A]) : Ordering[A]

因此,如果您将comparable: A with Comparable[A]传递给期待Ordered[A]的内容,则会执行此操作:

Ordered.orderingToOrdered(comparable)(Ordering.ordered(Predef.identity(comparable)))

现在,关于你的问题:使用存在类型是处理Java原始类型的正确方法。理论上,这可能导致错误的排序,但实际上,极不可能。但是,可能存在隐式歧义问题,因为Scala已经进行了Comparable => Ordered隐式转换,如上所示。