问题描述
我有一个类型类Search
,如果我们有一个TypeClass1[A]
或TypeClass2[A]
实例,则它有一个实例Search[A]
.优先考虑1
实例.
I have a typeclass Search
, which has an instance Search[A]
if we have a TypeClass1[A]
or a TypeClass2[A]
instance. With preference given to the 1
instance.
以下编译:
trait TypeClass1[A]
trait TypeClass2[A]
trait Search[A]
object Search extends LPSearch {
implicit def case1[A](implicit ev: TypeClass1[A]): Search[A] = null
}
trait LPSearch {
implicit def case2[A](implicit ev: TypeClass2[A]): Search[A] = null
}
object Test {
implicit val ev1: TypeClass1[Int] = null
implicit val ev2: TypeClass2[Int] = null
implicitly[Search[Int]]
}
这是我所期望的,隐式搜索找到case1
,找到ev1
,然后停止搜索.
This is as I would expect, the implicit search finds case1
, finds ev1
, and stops searching.
但是,如果我们将TypeClass2
更改为具有更多结构,则隐式搜索将停止工作:
However, if we change TypeClass2
to have more structure, the implicit search stops working:
trait TypeClass1[A]
trait TypeClass2[M[_], A]
trait Search[A]
object Search extends LPSearch {
// This is the same as before
implicit def case1[A](implicit ev: TypeClass1[A]): Search[A] = null
}
trait LPSearch {
implicit def case2[M[_], A](implicit ev: TypeClass2[M, A]): Search[M[A]] = null
}
object Test {
implicit val ev1: TypeClass1[List[Int]] = null
implicit val ev2: TypeClass2[List, Int] = null
// Does not compile:
implicitly[Search[List[Int]]]
}
在上面的示例中为什么最后一行没有编译?
Why does this last line not compile in the above example?
失败并显示ambiguous implicit values
,表示case1
和case2
都满足条件.
It fails with ambiguous implicit values
, saying both case1
and case2
satisfy the condition.
在scala 2.12.8和2.13.0上观察到的行为
Behaviour observed on scala 2.12.8 and 2.13.0
推荐答案
Scala规范说:
https://www .scala-lang.org/files/archive/spec/2.13/07-implicits.html#implicit-parameters
- 如果
- 1,否则为0, 如果从定义
- 1,否则为0.
A
与B
一样具体,则为B
的类或对象派生的类或对象中定义了A
,则为- 1 if
A
is as specific asB
, 0 otherwise, and - 1 if
A
is defined in a class or object which is derived from the class or object definingB
, 0 otherwise.
https://www .scala-lang.org/files/archive/spec/2.13/06-expressions.html#overloading-resolution
-
case1
是在一个对象中定义的,该对象是从定义case2
的类(特征)得出的(),反之亦然.
case1
is defined in an object which is derived from the class (trait) definingcase2
but not vice versa.
case2
与特定于 case1
,反之亦然.
因此case1
在case2
上的相对权重是1 + 0 = 1,而case2
在case1
上的相对权重是0 + 1 = 1.所以这很模棱两可.
So relative weight of case1
over case2
is 1+0=1 and relative weight of case2
over case1
is 0+1=1. So it's ambiguity.
Error: ambiguous implicit values:
both method case2 in trait LPSearch of type [M[_], A](implicit ev: App.TypeClass2[M,A])App.Search[M[A]]
and method case1 in object Search of type [A](implicit ev: App.TypeClass1[A])App.Search[A]
match expected type App.Search[List[Int]]
implicitly[Search[List[Int]]]
在第二种情况下,没有意义使用低优先级特征,因为如果两个隐式对象都与预期类型匹配,则当在同一对象中定义它们时,优选使用case2
.所以尝试
In the second case there is no sense to use low-priority trait since if both implicits match expected type, case2
is preferred when they are defined in the same object. So try
object Search {
implicit def case1[A](implicit ev: TypeClass1[A]): Search[A] = null
implicit def case2[M[_], A](implicit ev: TypeClass2[M, A]): Search[M[A]] = null
}
这篇关于为什么会发生这种隐含的歧义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!