订购,订购和比较选项

Knu*_*daa 22 scala

鉴于:

case class Person(name: String)
Run Code Online (Sandbox Code Playgroud)

并尝试做:

scala> List(Person("Tom"), Person("Bob")).sorted
Run Code Online (Sandbox Code Playgroud)

导致对失踪订购的投诉.

<console>:8: error: could not find implicit value for parameter ord: Ordering[Person]
   List(Person("Tom"), Person("Bob")).sorted
Run Code Online (Sandbox Code Playgroud)

不过这个:

case class Person(name: String) extends Ordered[Person] {
  def compare(that: Person) = this.name compare that.name }
Run Code Online (Sandbox Code Playgroud)

按预期工作正常:

scala> List(Person("Tom"), Person("Bob")).sorted
res12: List[Person] = List(Person(Bob), Person(Tom))
Run Code Online (Sandbox Code Playgroud)

虽然没有涉及订购或暗示.

问题1:这里发生了什么?(我的钱是隐含的......)

但是,考虑到上述事实,这个事实:

scala> Person("Tom") > Person("Bob")
res15: Boolean = true
Run Code Online (Sandbox Code Playgroud)

工作,这也是:

scala> List(Some(2), None, Some(1)).sorted
Run Code Online (Sandbox Code Playgroud)

开箱即用:

res13: List[Option[Int]] = List(None, Some(1), Some(2))
Run Code Online (Sandbox Code Playgroud)

我希望这个:

scala> Some(2) > Some(1)
Run Code Online (Sandbox Code Playgroud)

也会有效,但不会:

<console>:6: error: value > is not a member of Some[Int]
       Some(2) > Some(1)
Run Code Online (Sandbox Code Playgroud)

问题2:为什么不,我怎样才能让它发挥作用?

psp*_*psp 29

如果您安装稍微过于神奇的默认范围内的奖励,则可以比较以下选项:

scala> import scala.math.Ordering.Implicits._
import scala.math.Ordering.Implicits._

scala> def cmpSome[T: Ordering](x: Option[T], y: Option[T]) = x < y
cmpSome: [T](x: Option[T], y: Option[T])(implicit evidence$1: Ordering[T])Boolean
Run Code Online (Sandbox Code Playgroud)

导入使用中缀操作向您提供从Ordering到类的隐式,这样就可以在没有其他导入的情况下获得Ordering.


Mor*_*itz 10

关于你的第一个问题:Ordered[T]延伸Comparable[T].的Ordering同伴对象提供的隐式Ordering[T]为可被转换成一个任意值Comparable[T]:

implicit def ordered[A <% Comparable[A]]: Ordering[A]
Run Code Online (Sandbox Code Playgroud)

没有隐式转换A : Ordering => Ordered[A]- 这就是为什么Some(1) > Some(2)不起作用的原因.

如果定义这样的转换是一个好主意是值得怀疑的,因为你可能最终将对象包装到Ordered实例中然后再创建一个Ordering(等等......).更糟糕的是:您可以在范围内创建Ordered具有不同Ordering实例的两个实例,这当然不是您想要的.