如何调试和修复Diverging隐式

时间:2019-05-13 11:43:27

标签: scala implicit

我是scala的初学者,并且我试图将自己的头放在分散的隐式扩展上。

这是我的玩具代码:


class FooList[T](implicit ord: Ordering[T]) {

}

class Human(val score: Int) extends Ordering[Human] {


  override def compare(x: Human, y: Human): Int = {
    return x.score.compareTo(y.score);  
  }
}


object Main {

  def main(args: Array[String]): Unit = {
    val h = new Human(100)
    val lst = new FooList[Human]();
  }
}

我遇到错误:

diverging implicit expansion for type Ordering[Human]
starting with method comparatorToOrdering in trait LowPriorityOrderingImplicits


not enough arguments for constructor FooList: (implicit ord: Ordering[Human])FooList[Human].
Unspecified value parameter ord.

https://scastie.scala-lang.org/wkSrZ6BMQKW9ZJrsZhlITQ

我会喜欢一个或两个正确方向的指针:)

1 个答案:

答案 0 :(得分:4)

“发散”消息在这里有点令人困惑,真正的问题是对类型类如何工作的误解。它应该是这样的:

class FooList[T](implicit ord: Ordering[T]) {
}

case class Human(score: Int)

implicit object HumanOrdering extends Ordering[Human] {
  def compare(x: Human, y: Human): Int =
    x.score.compareTo(y.score)
}

object Main {
  def main(args: Array[String]): Unit = {
    val h = new Human(100)
    val lst = new FooList[Human]()
  }
}

请注意,Human类只是一种简单的数据类型。有一个单独的implicit object,它通过扩展Human来实现Ordering[Human]对象的排序。

关于类型类的要点是,该行为不是原始类的一部分,而是通过创建适当类型的implicit值来绑定到该类。这样,您就可以向类中添加多种行为,而不必修改基础类本身。


请注意,如果您想使内容更整洁,可以将此implicit object放在类对象中:

object Human {
  implicit object HumanOrdering extends Ordering[Human] {
    def compare(x: Human, y: Human): Int =
      x.score.compareTo(y.score)
  }
}