Why do we have to explicitly import implicit conversions having implicit parameters from companion objects? Strange.

StackOverflow https://stackoverflow.com/questions/22764272

Question

Let's consider this code:

class A
object A{
  implicit def A2Int(implicit a:A)=1
  implicit def A2String(a:A)="Hello"
}

object Run extends App{
  implicit val a: A =new A

  import A.A2Int
  // without this import this code does not compile, why ?
  // why is no import needed for A2String then ?

  def iWantInt(implicit i:Int)=println(i)
  def iWantString(implicit s:String)=println(s)

  iWantInt
  iWantString(a)
}

It runs and prints:

1
Hello

Now, if we comment out the line

import A.A2Int

then we get a compilation error:

enter image description here

With the line commented out, why Scala cannot find A.A2String if it can find A.A2Int ?

How can this problem be fixed ?

Thanks for reading.

Was it helpful?

Solution

The difference is that when you do iWantString(a), the compiler gets some starting point to work from: you are explicitly passing a, which the compiler knows is of type A. Given that iWantString takes a String and not an A, the compiler will search for an implicit conversion from A to String in order to insert it and make the call succeed. Implicit lookup rules state that the compiler must look (among other places) in the companion object of class A because type A is the source type of the conversion. This is where it finds the implicit conversion A2String. What you must get from this is that it is only because you passed an instance of A that the compiler knew to look for implicit conversions into the companion object of A.

When you just do iWantInt, the compiler has no reason to look into A, so it won't find your method A2Int (and as no other method/value in scope provides an implicit value of type Int, compilation then fails).

For more information about implicit lookup rules, see the See the scala specification at http://www.scala-lang.org/docu/files/ScalaReference.pdf (chapter 7.2). Here's the most relevant excerpt:

The implicit scope of a type T consists of all companion modules (§5.4) of classes that are associated with the implicit parameter’s type.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top