斯卡拉隐式排序

时间:2014-09-08 22:13:11

标签: scala implicit

我有没有办法为两个不同的类定义相同的隐式排序?

我尝试按照以下几行做一些事情,但它没有检测到排序。

abstract class Common
case class A extends Common
case class B extends Common

implicit val KeyOrdering = new Ordering[Common] {
    override def compare(x: Common, y: Common): Int = {
      x.toString.compareTo(y.toString)
   }
}

2 个答案:

答案 0 :(得分:24)

正如@ntn所指出的,列表的推断类型 - 它的两个元素的最小上限 - 是Product with Serializable with Common。由于scala.Ordering在其类型参数上不是逆变量,因此隐式解析失败,因为它不包含Ordering[Common] <: Ordering[Product with Serializable with Common]

您可以通过编写隐式排序来解决此问题,以便它始终具有所考虑的隐式参数的确切类型:

abstract class Common
case class A() extends Common
case class B() extends Common

object Common {
  implicit def ordering[A <: Common]: Ordering[A] = new Ordering[A] {
    override def compare(x: A, y: A): Int = {
      x.toString.compareTo(y.toString)
    }
  }
}

或者简洁:

object Common {
  implicit def ordering[A <: Common]: Ordering[A] = Ordering.by(_.toString)
}

答案 1 :(得分:2)

如果删除A和B的案例类(或者甚至只删除其中一个案例类),那么它可以正常工作。 对于List(A(), B()).sorted,它无法为Ordering找到Product with Serializable with C,因为A和B的基类是带C的产品(由于A和B都是案例类)。

如果要创建包含两种不同基类型的元素的列表,我假设您需要一个类型为List[C]的列表,您可以在使用它们之前声明元素(或从某些返回的函数中获取它们)输入C

val a: C = A()
val b: C = B()
List(a,b).sorted