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?
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.
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.
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