Reputation: 663
I'm trying to add a helper method to a config library by using implicit
classes and type classes. However, I am extremely new to Scala (1 week) and have been unable to find out why the following code issues a compile error (I provide the working solution in a comment in the code)
Simplification of the third party package:
package pkg
class Config {
def hasPath(path: String) = { false }
def getString(path: String) = { "str" }
def getInt(path: String) = { 7 }
def getDouble(path: String) = { 3.14d }
}
And my example file:
import pkg._
object Helpers {
trait Extractor[T] {
def extract(cfg: Config, path: String): T
}
object Extractor {
implicit object IntExtractor extends Extractor[Int] {
def extract(cfg: Config, path: String) = {
99
}
}
}
implicit class BetterConfig(cfg: Config) {
def extract[T](path: String)(implicit extractor: Extractor[T]): T = {
extractor.extract(cfg, path)
}
// This example works if I add the implicit parameter:
// (implicit extractor: Extractor[T])
def extract[T](path: String, default: T): T = {
if ( cfg.hasPath(path) ) {
extract[T](path)
// ^ error here
} else {
default
}
}
}
}
object Demo extends App {
import Helpers._
val cfg = new Config
val x = cfg.extract("foo", 3)
println(s"x: ${x}")
}
This code gives the error could not find implicit value for parameter extractor: Helpers.Extractor[T]
Why can't the implicit value be found when calling extract(path)
from within extract(path, default)
? My understanding of the scoping rules or resolving the implicit, is wrong. I would have thought that when the call to extract(path)
was made from within extract(path, default)
, the implicit would still be resolved from the companion object of Extractor
.
I have tried this with Scala 2.10.6 and 2.11.8.
Upvotes: 1
Views: 252
Reputation: 170745
Your call needs an implicit Extractor[T]
, where nothing is known about T
. It would be resolved from the companion object, if there was one, but there is no such method there.
Imagine it worked. Then
val cfg = new Config
val x = cfg.extract[String]("foo", "")
should also compile. But how would it work without an implicit Extractor[String]
anywhere?
Upvotes: 2