我希望在再次隐含forgetBA
之后编译以下代码。
trait ImplicitExample {
trait AA[T]
trait AB[T] extends AA[T]
trait BA[T] extends AA[T]
trait BB[T] extends AB[T] with BA[T]
object AA {
implicit def forgetAB[T: AB]: AA[T] = implicitly[AA[T]]
/*implicit*/ def forgetBA[T: BA]: AA[T] = implicitly[AA[T]]
}
object AB {
implicit def forgetBB[T: BB]: AB[T] = implicitly[AB[T]]
}
object BA {
implicit def forgetBB[T: BB]: BA[T] = implicitly[BA[T]]
}
object BB {
implicit object BBInt extends BB[Int]
}
val AAInt = implicitly[AA[Int]]
}
据我所知,这会导致模糊的隐式解决问题,所以我正在寻找一种方法来表明对一种隐式解决方案的偏好而不是另一种。
我听说有传言说以某种方式插入中间特征可能有所帮助,但我似乎无法找到解释。
答案 0 :(得分:4)
通常的诀窍是写下这样的东西:
trait LowPriorityAAInstances {
implicit def forgetAB[T: AB]: AA[T] = implicitly[AA[T]]
}
object AA extends LowPriorityAAInstances {
implicit def forgetBA[T: BA]: AA[T] = implicitly[AA[T]]
}
这为forgetBA
AA
的{{1}}实例提供了T
优先级,其中BA
的实例为AB
(同时仍在编译如果有AA
左右的实例。
命名完全取决于约定,但使用它来表明您只是以这种方式分解{{1}}的定义以适应隐式搜索是一个好主意机构。