24

I was reading about type classes where implicit objects were mentioned:

object Math { trait NumberLike[T] { def plus(x: T, y: T): T def divide(x: T, y: Int): T def minus(x: T, y: T): T } object NumberLike { implicit object NumberLikeDouble extends NumberLike[Double] { def plus(x: Double, y: Double): Double = x + y def divide(x: Double, y: Int): Double = x / y def minus(x: Double, y: Double): Double = x - y } implicit object NumberLikeInt extends NumberLike[Int] { def plus(x: Int, y: Int): Int = x + y def divide(x: Int, y: Int): Int = x / y def minus(x: Int, y: Int): Int = x - y } } } 

What are they? Where are they described? I only found definition of implicit classes on the web but not of implicit objects.

2 Answers 2

32

In Scala, objects and values are treated mostly the same. An implicit object can be thought of as a value which is found in the process of looking up an implicit of its type.

In your example, if one implicitly looks for a NumberLike type class with type parameter Double or Int, one will find NumberLikeDouble and NumberLikeInt.

implicit object NumberLikeDouble extends NumberLike[Double] 

is thus roughly the same as

implicit val NumberLikeDouble: NumberLike[Double] = new NumberLike[Double] { ...} 

or

implicit def NumberLikeDouble: NumberLike[Double] = new NumberLike[Double] { ...} 

Like a val, there is only a single value of that type and instantiation is not needed.


A simple use case:

import Math.NumberLike def sum[A](x: A, y: A)(implicit nl: NumberLike[A]) = nl.plus(x, y) sum(4, 5) // finds NumberLikeInt 
Sign up to request clarification or add additional context in comments.

4 Comments

Is there any difference between the implicit val and implicit def equivalent declarations ? Or are the three implicit declarations (implicit object, def, val) completely interchangeable ?
The object and val variants create the value only once, whereas with def you would instantiate the NumberLike each time it is looked up. For a stateless type class (no value or type parameters) it therefore makes more sense to use object or val. The object creates a "proper" class, so to say, whereas the val in this case creates an anonymous sub-class.
Thanks for clarification, so object and val are completely equivalent in all respect?
Unless you add members to the type. For example, val Foo = new { def bar = 33 }. If you call Foo.bar, Scala must use runtime reflection to handle that method, and it is deprecated. In those cases, using object Foo { def bar = 33 } creates a "real" class description including that method.
1

Thanks to implicit objects, you can define:

def mymethod[T : NumberLike](value: T): T = { implicitly[NumberLike[T]].plus(value, value) } 

which allows you to call your methods on Double and Floats because you have objects to deal with them.

scala> mymethod(1.0) res0: Double = 2.0 scala> mymethod(2) res0: Int = 4 scala> mymethod("test") //Error 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.