考虑以下示例:
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
SCASTIE
可以看出,所需的隐式在范围内,但编译器无法识别。
为什么会发生这种情况,是否有调用 foo
的解决方法?
最佳答案
如果你改变foo(v)
至 foo(v)(tp)
它会(稍微)更好地解释为什么它不想使用 tp。
简而言之,def foo[A : TypeClass]
想要隐式类型 TypeClass[A]
.
当你做 foo(v)
, A 变为 Test[_ <: ST]
这意味着“Test
是一些特定但ST
的未知子类型”。所以,foo
想要一个隐含的那个特定类型。
但是tp
不是那个。它是“Test
的 TypeClass 或 ST
的任何子类”(显然 _
在这两种情况下的意思略有不同,因为 v
是一个具体实例,必须具有特定类型)。
长话短说,Test[_ <: ST]
不是 v
的实际类型,而是其类型的父类(super class)型。所以,要让它工作,你只需要制作 TypeClass
逆变( TypeClass[-A]
) - 这将使 foo
接受 tp
作为隐式,因为它的类型将是它期望的子类型。
https://stackoverflow.com/questions/67136631/