在Scala中的隐式实例中强制执行优先级

时间:2016-05-03 06:14:55

标签: scala typeclass implicit

这是问题Scala implicit typeclass precedence in companion objects的后续行动。

假设我有两个特征Trait2 extends Trait1。每个特征都有一个特定的类型类实例Eq。我想让Trait2的类型类实例的优先级高于Trait1的tha。但是,下面的代码(LowPriorityImplicits技巧)不起作用。

trait Eq[-A] {
  def eq(a: A, b: A): Boolean
}

object Eq {
  implicit object IntEq extends Eq[Int] {
    def eq(a: Int, b: Int) = a == b
  }
}

trait Trait1[+A]
trait Trait2[+A] extends Trait1[A]

object Implicits extends LowPriorityImplicits {
  implicit def Eq2[T: Eq]: Eq[Trait2[T]] = ???
}

trait LowPriorityImplicits {
  implicit def Eq1[T: Eq]: Eq[Trait1[T]] = ???
}

object Test2 extends App {

  def f[T: Eq](x: T) = ???
  import Implicits._

  val t1 = new Trait1[Int] {}
  val t2 = new Trait2[Int] {}

  f(t2) // COMPILATION ERROR!

}

抛出以下编译错误:

Error:(33, 4) ambiguous implicit values:
 both method Eq1 in trait LowPriorityImplicits of type [T](implicit evidence$2: Eq[T])Eq[Trait1[T]]
 and method Eq2 in object Implicits of type [T](implicit evidence$1: Eq[T])Eq[Trait2[T]]
 match expected type Eq[Trait2[Int]]
  f(t2)
   ^

如何强制执行类型类实例的优先级关系?

1 个答案:

答案 0 :(得分:1)

类型参数的差异不能与Scala的类型类编码很好地配合。如果要编译,只需尝试一下即可。

trait Eq[A] {
  def eq(a: A, b: A): Boolean
}

object Eq {
  implicit object IntEq extends Eq[Int] {
    def eq(a: Int, b: Int) = a == b
  }
}

trait Trait1[A]
trait Trait2[A] extends Trait1[A]

object Implicits extends LowPriorityImplicits {
  implicit def Eq2[T: Eq]: Eq[Trait2[T]] = ???
}

trait LowPriorityImplicits {
  implicit def Eq1[T: Eq]: Eq[Trait1[T]] = ???
}

object Test2 extends App {

  def f[T: Eq](x: T) = ???
  import Implicits._

  val t1 = new Trait1[Int] {}
  val t2 = new Trait2[Int] {}

  f(t2) // COMPILATION ERROR!

}

如果您确实希望Eq[Trait2[A]]的行为类似于Eq[Trait1[A]]的子类型,则可以使用隐式转换作为解决方法。