Reputation: 5206
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
.
Upvotes: 23
Views: 3156
Reputation: 1918
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.
Upvotes: 16