【问题标题】:Enforcing precedence in implicit instances in Scala在 Scala 中的隐式实例中强制执行优先级
【发布时间】:2019-03-29 21:39:59
【问题描述】:

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

假设我有两个特征,Trait2 extends Trait1。每个特征都有一个特定的类型类实例Eq。我想让Trait2 的类型类实例的优先级高于Trait1 的优先级。但是,下面的代码(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)
   ^

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

【问题讨论】:

    标签: scala typeclass implicit


    【解决方案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]] 的子类型,您可以使用隐式转换作为解决方法。

    【讨论】:

      猜你喜欢
      • 2016-10-20
      • 2020-07-06
      • 1970-01-01
      • 2012-01-27
      • 2016-08-24
      • 2014-02-24
      • 2012-09-19
      • 2011-11-28
      • 2021-09-03
      相关资源
      最近更新 更多