6

I'm confused by this description in "5.1.3 Implicit resolution" in Joshua Suareth's book Scala in depth, on Page 100:

Scala objects can't have companion objects for implicits. Because of this, implicits associated with the object's type, that are desired on the implicit scope of that object's type, must be provided from an outer scope. Here's an example:

scala> object Foo {
     |   object Bar { override def toString = "Bar" }
     |   implicit def b : Bar.type = Bar 
     |}
defined module Foo
scala> implicitly[Foo.Bar.type]
res1: Foo.Bar.type = Bar

But while I make object Bar implicit in REPL:

scala> object Foo {
     |   implicit object Bar {
     |     override def toString = "isBar" }
     | }
defined module Foo
scala> implicitly[Foo.Bar.type]
res0: Foo.Bar.type = isBar

It seems that it doesn't need to define an implicit in the outer scope. Or do I take Joshua's meaning completely wrong?

3
  • 1
    When was the book written, and what version of Scala are you using? This might have changed a bit in 2.9 or 2.10. Commented Mar 19, 2013 at 13:15
  • 1
    Things are as in my answer at least from 2.9.x on. Josh must have been referring to Scala pre-2.9, or just been unaware of the semantics. FTR I was both surprised and delighted when I discovered that this was possible. Commented Mar 19, 2013 at 13:56
  • Thanks for the reply. It's suggested in this book that it covers 2.7.x to 2.9.x. I have 2.10 installed on my machine which might behave differently. Commented Mar 19, 2013 at 15:32

2 Answers 2

8

In this scenario objects act as if they were their own companions, so you simply need to nest your object-type-mentioning implicits in the body of the object itself,

scala> object Bar {
     |   override def toString = "Bar"
     |   implicit def b : Bar.type = Bar
     | }
defined module Bar

scala> implicitly[Bar.type]
res0: Bar.type = Bar

Note that here the body of Bar has been considered as part of the implicit scope for resolving Bar.type.

This might appear to be an obscure corner of Scala's type system, but I was able to put it to good use in shapeless's encoding of polymorphic (function) values.

Sign up to request clarification or add additional context in comments.

Comments

2

If you put the following code in a file and try to compile using scalac it fails with a 'implicit' modifier cannot be used for top-level objects

 implicit object Foo {
  object Bar { override def toString = "Bar" }
 }

This however compiles fine:

 object Foo {
  implicit  object Bar { override def toString = "Bar" }
 }

I believe using the REPL implicit's are not exactly top-level hence the seeming inconsistency.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.