I've seen two ways (one less than the other) of declaring implicit
for typeclass pattern in Scala.
implicit val instance1 = new Typeclass { def do = ??? }
implicit object instance2 extends Typeclass { def do = ??? }
How are they different? Should one prefer one to the other for certain times? I find implicit val
much more commonly used than implicit object
and I've yet to find many resources about implicit object
.
Language. A method can have an implicit parameter list, marked by the implicit keyword at the start of the parameter list. If the parameters in that parameter list are not passed as usual, Scala will look if it can get an implicit value of the correct type, and if it can, pass it automatically.
In simpler terms, if no value or parameter is passed to a method or function, then the compiler will look for implicit value and pass it further as the parameter. For example, changing an integer variable to a string variable can be done by a Scala compiler rather than calling it explicitly.
An implicit class is a class marked with the implicit keyword. This keyword makes the class's primary constructor available for implicit conversions when the class is in scope. Implicit classes were proposed in SIP-13.
In this case, it looks inside the object Ordering , companion to the class Ordering , and finds an implicit Ordering[Int] there. This is how Scala found the implicit Numeric[Int] and Numeric[Long] in your question, by the way, as they are found inside Numeric , not Integral .
One difference is that the object
version is going to be lazily initialized, i.e. it's constructor will not be called until the first time it is used. For example:
trait Incrementer[T] {
def inc(x: T)
}
def increment[T](x: T)(implicit ev: Incrementer[T]) = ev.inc(x)
implicit object IntIncrementer extends Incrementer[Int] {
println("IntIncrementer is being constructed...")
def inc(x: Int) = x + 1
}
implicit val DoubleIncrementer extends Incrementer[Double] {
println("DoubleIncrementer is being constructed...")
def inc(x: Double) = x + 1D
}
Note that you will not see the message from IntIncrementer
until it is used, e.g.
increment(1) //this prints "IntIncrementer is being constructed..."
The message from DoubleIncrementer
, however, will be displayed when it is defined. So the initialization of implicit object
is lazy while the initialization of implicit val
is strict.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With