【问题标题】:Implicit not found while it's presented in the scope在范围内显示时未找到隐式
【发布时间】:2021-07-12 03:40:26
【问题描述】:

考虑以下示例:

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

【问题讨论】:

    标签: scala typeclass implicit


    【解决方案1】:

    如果您将foo(v) 更改为foo(v)(tp),它会(稍微)更好地解释为什么它不想使用 tp。

    简而言之,def foo[A : TypeClass] 需要 TypeClass[A] 类型的隐式。 当您执行foo(v) 时,A 变为Test[_ &lt;: ST],这意味着“Test 的某些特定但未知的ST 子类型”。所以,foo 想要一个隐含的 那个 特定类型。

    tp 不是。它是“Test 的 TypeClass 或 STany 子类”(显然 _ 在这两种情况下的含义略有不同,因为 v 是一个具体实例,它必须具有特定类型)。

    长话短说,Test[_ &lt;: ST] 不是 v 的实际类型,而是其类型的超类型。所以,要让它工作,你只需要使 TypeClass 逆变 (TypeClass[-A]) - 这将使 foo 接受 tp 作为隐式,因为它的类型将是它所期望的子类型。

    【讨论】:

    • 调用foo[Test[_ &lt;: ST]](v) 的效果如何?
    • @SomeName 在这里,您正在“铸造”v,从“ST 的某些特定但未知的子类的测试”到它的超类型“ST 的任何子类的测试”,并且有效,因为 that 类型 (tp) 的隐式 TypeClass 在范围内。
    【解决方案2】:

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

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

    但是,如果您明确提供类型变量实例 foo[Test[_ &lt;: ST]](v),那么隐式解析应该可以工作,因为我们已经过了推理阶段。

    它在 Scala 3 中工作可能是因为它在内部将 rewrites 存在类型转为精炼类型。

    【讨论】:

      猜你喜欢
      • 2022-01-07
      • 2014-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-23
      • 2021-06-18
      • 2021-01-15
      • 1970-01-01
      相关资源
      最近更新 更多