Scala 隐式排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25733902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:32:56  来源:igfitidea点击:

Scala Implicit Ordering

scalaimplicit

提问by Olshansk

Is there a way for me to define the same implicit ordering for two different classes?

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

I tried to do something along the following lines but it doesn't detect the ordering.

我试图按照以下方式做一些事情,但它没有检测到排序。

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

回答by J Cracknell

As noted by @ntn, the inferred type of your list - the least upper bound of its two elements - is Product with Serializable with Common. As scala.Orderingis not contravariant on its type parameter, implicit resolution fails because it does not hold that Ordering[Common] <: Ordering[Product with Serializable with Common].

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

You can work around this by writing the implicit ordering so that it always has the exact type of the implicit parameter under consideration:

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

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

Or for concision:

或者为了简洁:

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

回答by ntn

If you remove the case class for A and B (or even only for one of them), then it works. For List(A(), B()).sorted, it fails to find an Orderingfor Product with Serializable with C, as the base class for A and B is Product with C (due to A and B being both case classes).

如果您删除 A 和 B 的案例类(或什至仅删除其中之一),那么它就可以工作。对于List(A(), B()).sorted,它找不到Orderingfor Product with Serializable with C,因为 A 和 B 的基类是 Product with C(因为 A 和 B 都是 case 类)。

If you are creating a list with elements of two different base types, I assume you want a list of type List[C], in which you can declare the elements before using them (or get them from some function which returns type C.

如果您正在创建一个包含两种不同基本类型元素的列表,我假设您需要一个 type 列表List[C],您可以在其中声明元素,然后再使用它们(或者从某个返回 type 的函数中获取它们C

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