Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Scala fail to find a secondary implicit value in this one particular case?

I am having a hard time explaining the difference in behavior between additional implicit values sought by either a primary implicit value or an implicit conversion. Specifically, this works:

trait Foo[A]
implicit def fooString: Foo[String] = null

implicit def value[A](implicit foo: Foo[A]) = 5

> implicitly[Int]
5

But this does not:

implicit def conversion[A](x: Int)(implicit foo: Foo[A]) = new {
    def aMethod = 5
}

> 1.aMethod
could not find implicit value for parameter foo: test.Foo[A]

Varying:

  • Whether the search is started by implicitly or an implicit conversion
  • Whether the secondary implicit value sought after is polymorphic
  • Whether the secondary implicit value supplied is polymorphic

I get the following results:

Conversion/value  Searching for  Supplied | Works?
----------------  -------------  -------- | ------
     conversion     poly          poly    |  yes
     conversion     poly          mono    |  **no**
     conversion     mono          poly    |  yes
     conversion     mono          mono    |  yes
     value          poly          poly    |  yes
     value          poly          mono    |  yes
     value          mono          poly    |  yes
     value          mono          mono    |  yes

As you can see, the only case that does not work is when the search is started by an implicit conversion, the value sought is polymorphic, yet the value supplied is monomorphic.

Is there a theoretical reason why this should be the case, or is this a bug/limitation of Scala?

like image 811
Owen Avatar asked Feb 04 '12 04:02

Owen


2 Answers

You're being bitten by scalac bug SI-3346. More generally see the description of SI-4699, esp. point (1),

1) implicit search and implicit conversion search treat undetermined type parameters differently

which you're observing directly where your cases are distinguishing between implicit values and implicit conversions.

I've updated SI-3346 to include this as an additional example.

like image 142
Miles Sabin Avatar answered Nov 11 '22 10:11

Miles Sabin


Change the signature of the implicit conversion the following way:

implicit def conversion[A](a: A)(implicit foo: Foo[A]) = new {

Then call aMethod on a value of type for which an implicit value is defined, i.e. with a String:

scala> "foo".aMethod
res0: Int = 5
like image 38
Heiko Seeberger Avatar answered Nov 11 '22 09:11

Heiko Seeberger