考虑以下示例:
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
斯卡斯蒂
可以看出,所需的隐式在范围内,而编译无法识别它。
为什么会发生这种情况?是否有解决方法 foo
?
2条答案
按热度按时间tag5nh1u1#
在隐式解析期间不推断存在类型,因此
f(v)
失败,因为它正在查找具有非推断类型的隐式值但是,您是否显式地提供了类型变量示例
foo[Test[_ <: ST]](v)
因为我们已经过了推理阶段,所以隐式解析应该是有效的。它在Scala3中工作可能是因为它在内部将存在类型重写为精炼类型。
rta7y2nd2#
如果你改变了
foo(v)
至foo(v)(tp)
它会更好地解释为什么它不想使用tp。简而言之,
def foo[A : TypeClass]
需要类型的隐式TypeClass[A]
. 当你这么做的时候foo(v)
,a变为Test[_ <: ST]
这意味着Test
某些特定但未知的ST
". 所以,foo
需要该特定类型的隐式。但是
tp
不是那样的。这是一个“类型类”Test
或者任何一个子类ST
“(显然_
在这两种情况下意味着稍微不同的事情,因为v
是一个具体示例,必须具有特定类型)。长话短说,
Test[_ <: ST]
不是实际的v
,但它是其类型的超类型。所以,要想成功,你只需要TypeClass
逆变(TypeClass[-A]
)-那就好了foo
接受tp
因为它的类型将是它所期望的子类型。