简体   繁体   English

在 scope 中显示时未找到隐式

[英]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

SCASTIE 斯卡斯蒂

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM