[英]Implicit not found while it's presented in the scope
Consider the following example:考虑以下示例:
sealed trait ST
object ST{
case class ST1() extends ST
case class ST2() extends ST
}
trait TypeClass[A]{
def doSome(a: A): Unit
}
case class Test[T](t: T)
implicit val tp: TypeClass[Test[_ <: ST]] = ??? //the implicit
def foo[A: TypeClass](a: A) = implicitly[TypeClass[A]].doSome(a)
val v: Test[_ <: ST] = ???
foo(v) //error: implicit not found
As can be seen the required implicit is in scope while it is not recognized by the compile.可以看出,所需的隐式在 scope 中,而编译器无法识别。
Why does that happen and is there a workaround to call foo
?为什么会发生这种情况,是否有解决方法可以调用foo
?
If you change foo(v)
to foo(v)(tp)
it'll explain (a little bit) better why it doesn't want to use tp.如果您将foo(v)
更改为foo(v)(tp)
,它将(稍微)更好地解释为什么它不想使用 tp。
In a nutshell, def foo[A: TypeClass]
wants an implicit of type TypeClass[A]
.简而言之, def foo[A: TypeClass]
需要TypeClass[A]
类型的隐式。 When you do foo(v)
, A becomes Test[_ <: ST]
which means " Test
of some specific but unknown subtype of ST
".当您执行foo(v)
时, A 变为Test[_ <: ST]
,这意味着“ Test
某些特定但未知的ST
子类型”。 So, foo
wants an implicit for that specific type.因此, foo
想要该特定类型的隐式。
But tp
is not that .但tp
并非如此。 It is a "TypeClass for Test
or any subclass of ST
" (apparently _
means slightly different things in these two contexts, because v
is a concrete instance, that must have a specific type).它是“ Test
的 TypeClass 或ST
的任何子类”(显然_
在这两种情况下的含义略有不同,因为v
是一个具体的实例,它必须具有特定的类型)。
Long story short, Test[_ <: ST]
is not the actual type of v
, but a supertype of its type.长话短说, Test[_ <: ST]
不是v
的实际类型,而是其类型的超类型。 So, to make it work, you just need to make the TypeClass
contravariant ( TypeClass[-A]
) - that'll make foo
accept tp
as the implicit, because its type will be a subtype of what it expects.因此,要使其工作,您只需要使TypeClass
逆变( TypeClass[-A]
) - 这将使foo
接受tp
作为隐式,因为它的类型将是它所期望的子类型。
Existential types are not inferred during implicit resolution so f(v)
fails because it is looking for an implicit value with non-inferred type在隐式解析期间不会推断存在类型,因此f(v)
失败,因为它正在寻找具有非推断类型的隐式值
TypeClass[Test[_$4]]]
|
existential not inferred
however whey you explicitly provide the type variable instance foo[Test[_ <: ST]](v)
then implicit resolution should work because we are past inference stage.但是,如果您明确提供类型变量实例foo[Test[_ <: ST]](v)
,那么隐式解析应该可以工作,因为我们已经过了推理阶段。
It works in Scala 3 probably because internally it rewrites existential types to refined types.它在 Scala 3 中工作可能是因为它在内部将存在类型重写为精炼类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.