When implementing Typeclasses for our types, we can use different syntaxes (an implicit val
or an implicit object
, for example). As an example:
A Typeclass definition:
trait Increment[A] {
def increment(value: A): A
}
And, as far as I know, we could implement it for Int
in the two following ways:
implicit val fooInstance: Increment[Int] = new Increment[Int] {
override def increment(value: Int): Int = value 1
}
// or
implicit object fooInstance extends Increment[Int] {
override def increment(value: Int): Int = value 1
}
I always use the first one as for Scala 2.13 it has an abbreviation syntax that looks like this:
implicit val fooInstance: Increment[Int] = (value: Int) => value 1
But, is there any real difference between them? or is there any recommendation or standard to do this?
There is a related question about implicit defs and implicit classes for conversions, but I'm going more to the point of how to create (best practices) instances of Typeclasses, not about implicit conversions
CodePudding user response:
As far as I know the differences would be:
object
s have different initialization rules - quite often they will be lazily initialized (it doesn't matter if you don't perform side effects in constructor)- it would also be seen differently from Java (but again, you probably won't notice that difference in Scala)
object X
will have a typeX.type
which is a subtype of whateverX
extends or implements (but implicit resolution would find that it extends your typeclass, though perhaps with a bit more effort)
So, I wouldn't seen any difference in the actual usage, BUT the implicit val
version could generate less JVM garbage (I say garbage as you wouldn't use any of that extra compiler's effort in this particular case).