w0mTea
w0mTea

Reputation: 63

Import implicit values from a companion object but not used

I wrote some code which acquires some implicit values in the companion object like this:

package example.implicits

class Test {
  import Test.GetValue
  import Test.Implicits._

  val intV = getV[Int]
  val stringV = getV[String]

  private def getV[T](implicit getV: GetValue[T]): T = getV.value
}

object Test {
  trait GetValue[T] {
    def value: T
  }

  object Implicits {
    implicit val intValue = new GetValue[Int] {
      def value = 10
    }

    implicit val stringValue = new GetValue[String] {
      def value = "ten"
    }
  }
}

This piece of code cannot be compiled and the compiler complains it couldn't find the required implicit values. Note that my environment is

scala 2.11.8 on Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66

However, if I use these values explicitly, nothing goes wrong:

class Test {
  import Test.GetValue
  import Test.Implicits._

  val intV = getV[Int](intValue)
  val stringV = getV[String](stringValue)

  private def getV[T](implicit getV: GetValue[T]): T = getV.value
}

Further more, if I declare new implicit values as following:

class Test {
  import Test.GetValue
  import Test.Implicits._

  implicit val intValue1 = intValue

  implicit val stringValue1 = stringValue

  val intV = getV[Int]
  val stringV = getV[String]

  private def getV[T](implicit getV: GetValue[T]): T = getV.value
}

errors will be raised because of ambiguous implicit values.

When I swap position of class Test and object Test, everything goes right:

object Test {
  trait GetValue[T] {
    def value: T
  }

  object Implicits {
    implicit val intValue = new GetValue[Int] {
      def value = 10
    }

    implicit val stringValue = new GetValue[String] {
      def value = "ten"
    }
  }
}

class Test {
  import Test.GetValue
  import Test.Implicits._

  val intV = getV[Int]
  val stringV = getV[String]

  private def getV[T](implicit getV: GetValue[T]): T = getV.value
}

So why can't scala find implicit values after I've already imported them in the first case?

And why it can do so when I swap their position?

Upvotes: 2

Views: 1005

Answers (1)

Cyrille Corpet
Cyrille Corpet

Reputation: 5315

That's because the compiler hasn't infered the type of Test.intValue yet at the time when it resolves the implicits in getV[Int].

Just give Test.intValue and Test.stringValue their type explicitly, and your problem will be solved.

I read somewhere (sorry, can't remember where exactly), that implicit definitions should always be given an explicit type, notably to avoid this kind of behaviour.

Upvotes: 7

Related Questions