Could not find implicit value when using Context Bound

I use the following code written in Scala 2.11.8:

sealed trait Acceptable[T] object Acceptable { implicit object Int extends Acceptable[Int] implicit object String extends Acceptable[String] } case class Enc[T](f: T => Any) implicit def test[I, T](implicit f: I => T, a: Acceptable[T]): Enc[I] = Enc[I](f) val e = implicitly[Enc[Int]] 

It compiles successfully.

As you can see, the parameter a: Acceptable[T] should be easily converted to a context binding :

 implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] = Enc[I](f) 

But after that, the compilation of the changes fails with an error:

could not find implicit value for parameter e: app.Enc [Int]

Why is this happening?

UPDATE:

I tried the -Xlog-implicits option of the compiler, and the compilation log gives me:

 [info] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: test is not a valid implicit value for app.Enc[Int] because: [info] hasMatchingSymbol reported error: ambiguous implicit values: [info] both object Int in object Acceptable of type app.Acceptable.Int.type [info] and object String in object Acceptable of type app.Acceptable.String.type [info] match expected type app.Acceptable[T] [info] val e = implicitly[Enc[Int]] [info] ^ [info] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: app.test is not a valid implicit value for app.Enc[Int] because: [info] hasMatchingSymbol reported error: ambiguous implicit values: [info] both object Int in object Acceptable of type app.Acceptable.Int.type [info] and object String in object Acceptable of type app.Acceptable.String.type [info] match expected type app.Acceptable[T] [info] val e = implicitly[Enc[Int]] [info] ^ [error] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: could not find implicit value for parameter e: app.Enc[Int] [error] val e = implicitly[Enc[Int]] 

Ok, I understand this conclusion. But why does this work in the case of an implicit parameter?

+5
source share
1 answer

I don't have a link for this, but in my experience, a search matching the context binding is performed before any other "explicit" implicit parameters; your method

 implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] = Enc[I](f) 

equivalently

 implicit def test2[I, T](implicit a: Acceptable[T], f: I => T): Enc[I] = Enc[I](f) 

which, as you can easily check, also does not work. What for? from the output, it seems that the compiler first tries to search for the implicit Acceptable[T] , and it fails at this stage due to ambiguity; at that moment he stops looking for anything else. Which is misleading is the error message that IMHO should be something like "an unsuccessful search for valid [T]: ambiguous implications" or something like that.

Why does another method work? due to the order of implicit parameters. The compiler will search first for f: I => T , and this will most likely associate T with Int , and then we will have a unique Acceptable[Int] implicit form. Generally

  • I would not mix context bounds and implicit parameters
  • The order of implicit parameters is important, and they should be organized so that the search determines the next unique

As far as I know, all this is not specified and depends on the current implementation; above is based mainly on my experience of debugging implicits errors.

+7
source

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


All Articles