implicit在作用域中显示时未找到

6bc51xsx  于 2021-07-14  发布在  Java
关注(0)|答案(2)|浏览(437)

考虑以下示例:

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 ?

tag5nh1u

tag5nh1u1#

在隐式解析期间不推断存在类型,因此 f(v) 失败,因为它正在查找具有非推断类型的隐式值

TypeClass[Test[_$4]]]
                |
          existential not inferred

但是,您是否显式地提供了类型变量示例 foo[Test[_ <: ST]](v) 因为我们已经过了推理阶段,所以隐式解析应该是有效的。
它在Scala3中工作可能是因为它在内部将存在类型重写为精炼类型。

rta7y2nd

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 因为它的类型将是它所期望的子类型。

相关问题