I got really confused with Scala’s implicit,
so I wanted to summarize my findings and share how I learned it.
Definition
From the Tour-of-Scala tutorial, a parameter on a method can be marked as implicit, which implies that the parameter value will be taken from the context when it is called. The program will fail to compile if the implicit value is not resolved.
From the direct definitions, Scala look for implicit parameters in two different places:
- Scala will first look for implicit definitions and implicit parameters that can be accessed directly (without a prefix) at the point the method with the implicit parameter block is called.
- Then it looks for members marked implicit in all the companion objects associated with the implicit candidate type.
Examples
- This example is from here
abstract class Monoid[A] {
def add(x: A, y: A): A
def unit: A
}
object ImplicitTest {
implicit val stringMonoid: Monoid[String] = new Monoid[String] {
def add(x: String, y: String): String = x concat y
def unit: String = ""
}
implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
def add(x: Int, y: Int): Int = x + y
def unit: Int = 0
}
def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
if (xs.isEmpty) m.unit
else m.add(xs.head, sum(xs.tail))
def main(args: Array[String]): Unit = {
println(sum(List(1, 2, 3))) // uses intMonoid implicitly
println(sum(List("a", "b", "c"))) // uses stringMonoid implicitly
}
}
Key notes:
implicit
keyword in front ofstringMonoid()
andintMonoid()
methods indicates that the method can be used implicitly- in
sum()
, implicit parameter m means that we only need explicitly provide the first argumentxs
, which means the implicit parameter m needs to be implicitly defined - When
sum(List(1,2,3))
is called, Scala will look for an implicit in the scope. It passesA
a typeInt
, which means Scala will now look for an implicit of typeMonoid[Int]
. Therefore, the first method,intMonoid
is used - Also, when
sum(List(1,2,3))
is called, note thatintMonoid
can be accessed directly, therefore passed automatically
Scala will first look for implicit definitions and implicit parameters that can be accessed directly (without a prefix) at the point the method with the implicit parameter block is called.
Conclusion
Yes.. it is very confusing, and I still do not fully understand the details. I will update the post as I acquired deeper knowledge. Thanks for reading all!