Some Name
Some Name

Reputation: 9521

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.

Why does that happen and is there a workaround to call foo?

Upvotes: 2

Views: 306

Answers (2)

Mario Galic
Mario Galic

Reputation: 48400

Existential types are not inferred during implicit resolution so f(v) fails because it is looking for an implicit value with non-inferred type

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.

It works in Scala 3 probably because internally it rewrites existential types to refined types.

Upvotes: 4

Dima
Dima

Reputation: 40500

If you change foo(v) to foo(v)(tp) it'll explain (a little bit) better why it doesn't want to use tp.

In a nutshell, def foo[A : TypeClass] wants an implicit of type TypeClass[A]. When you do foo(v), A becomes Test[_ <: ST] which means "Test of some specific but unknown subtype of ST". So, foo wants an implicit for that specific type.

But tp is not that. 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).

Long story short, Test[_ <: ST] is not the actual type of v, but a supertype of its type. 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.

Upvotes: 5

Related Questions