Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implicits for objects in Scala

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?

like image 919
cfchou Avatar asked Mar 19 '13 11:03

cfchou


2 Answers

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.

like image 50
Miles Sabin Avatar answered Sep 21 '22 02:09

Miles Sabin


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.

like image 28
korefn Avatar answered Sep 20 '22 02:09

korefn