Scala Implicit Resolution

(Scala 2.11.8)

Consider the following code:

object ScalaTest extends App { class Wrapper { import Wrapper._ def init(): Unit = { // "could not find implicit value for parameter tc: ScalaTest.Wrapper.TC[Int]" printWithTC(123) // Compiles printWithTC(123)(IntTC) // Compiles again! printWithTC(132) } } object Wrapper { trait TC[A] { def text(a: A): String } implicit object IntTC extends TC[Int] { override def text(a: Int) = s"int($a)" } def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = { println(tc.text(a)) } } (new Wrapper).init() } 

I have a bunch of questions regarding this piece of code:

  • Why is IntTC not allowed in the first place?
  • Why does it compile after using it once? (if you comment out the first call, the code works)
  • Where should typeclass pointers be placed for proper resolution?
+5
source share
2 answers

Use val with an explicit return type. See https://github.com/scala/bug/issues/801 and https://github.com/scala/bug/issues/8697 (among others).
Implicit objects have the same problem as implicit vals and defs with supposed return types. As for your second question: when IntTC used explicitly, you force the compiler to check its type, so after that its type is known and can be found by an implicit search.

 class Wrapper { import Wrapper._ def init(): Unit = { // Compiles printWithTC(123) // Compiles printWithTC(123)(IntTC) // Compiles printWithTC(132) } } object Wrapper { trait TC[A] { def text(a: A): String } implicit val IntTC: TC[Int] = new TC[Int] { override def text(a: Int) = s"int($a)" } def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = { println(tc.text(a)) } } 

If you really want your implicit to be evaluated lazily as an object, you can use implicit lazy val with an explicit type.

+3
source

Define the implicit before using it.

 object Wrapper { trait TC[A] { def text(a: A): String } implicit object IntTC extends TC[Int] { override def text(a: Int) = s"int($a)" } def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = { println(tc.text(a)) } } class Wrapper { import Wrapper._ def init(): Unit = { // "could not find implicit value for parameter tc: ScalaTest.Wrapper.TC[Int]" printWithTC(123) // Compiles printWithTC(123)(IntTC) // Compiles again! printWithTC(132) } } (new Wrapper).init() 
0
source

Source: https://habr.com/ru/post/1268390/


All Articles