Implicit value not found in method to method call - scala

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.

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?

Related

Accessing implicit parameters explicitly at runtime

I'm trying to access an implicit parameter for a generic type. Scala is able to find the implicit just fine in the straightforward case by calling a method with an explicit generic type, such as with printGenericType[Person] below.
However, if I create a TypeTag[Person] and pass it to printGenericTypeGivenTypeTag, Scala is unable to find the implicit parameter.
case class Person(name: String)
case class Animal(age: Int)
implicit val p = Person("cory")
implicit val a = Animal(2)
def main(args: Array[String]): Unit = {
// Can find the implicit Person, prints "Hello Person(cory)"
printGenericType[Person]
// Can find the implicit Animal, prints "Hello Animal(2)"
printGenericType[Animal]
// See comment below
printNamedType("Person")
printNamedType("Animal")
}
def printGenericType[T](implicit t: T) = {
println(s"Hello $t")
}
def printGenericTypeGivenTypeTag[T](typeTag: TypeTag[T])(implicit t: T) = {
println(s"Hello $t")
}
def printNamedType[T](name: String) = {
val typetag: TypeTag[T] = getTypeTag[T](name)
// Cannot find the implicit of type T, compiler error
printGenericTypeGivenTypeTag(typetag)
}
def getTypeTag[T](name:String): TypeTag[T] = ... //Implementation irrelevant
If I understand correctly, Scala locates implicit parameters at compile time, so it makes sense that it can't find an implicit parameter for the generic type T at compile time.
However, I know that an implicit instance of T does exist. Is it possible to rewrite printGenericTypeGivenTypeTag in such a way as to find the implicit value for T? At runtime, the method has access to the actual type of T, so it seems it should be able to locate an implicit parameter of the same type that is in scope.
For the curious, the reasoning behind this is to avoid this:
name match {
case "Person" => printGenericType[Person]
case "Animal" => printGenericType[Animal]
}
To answer the question
You're not really wanting to pass the T implicitly, but rather the TypeTag, and not the T. Here's what I mean, and you're probably better off with an implicit value class.
implicit class GenericPrinter[T](val obj: T) extends AnyVal {
def printGenericType()(implicit tag: TypeTag[T]) = {
// do stuff with the tag
Console.println("Hello $obj")
}
}
val x: Person = Person(...)
x.printGenericType
Now solving the real problem
If you are trying to print case classes, I'd probably go down the implicit macro route for added convenience. It's really trivial to write up a macro that does this for us, e.g output a debug string based on all the constructor params of an arbitrary case class.
trait DeepPrinter[T <: Product with Serializable] {
/**
* Prints a deeply nested debug string for a given case class.
* This uses implicit macros to materialise the printer type class.
* In English, when we request for an implicit printer: DeepPrinter[T],
* the pre-defined compile time macro will generate this method for us
* based on the fields of the given case class.
*
* #param sep A separator to use to delimit the rows in a case class.
* #return A fully traced debug string so we can see how a case class looks like.
*/
def debugString(sep: String = "\n"): String
}
object DeepPrinter {
implicit def deepPrinter[T <: Product with Serializable] = macro DeepPrinterImpl.deepPrinterImpl[T]
}
And the macro is pretty trivial, looks kind of like this.
import language.experimental.macros
import scala.reflect.macros.blackbox
#macrocompat.bundle
class DeepPrinterImpl(val c: blackbox.Context) {
import c.universe._
object CaseField {
def unapply(symbol: TermSymbol): Option[(Name, Type)] = {
if (symbol.isVal && symbol.isCaseAccessor) {
Some(symbol.name -> symbol.typeSignature)
} else {
None
}
}
}
def fields(tpe: Type): Iterable[(Name, Type)] = {
tpe.decls.collect { case CaseField(nm, tpeSn) => nm -> tpeSn }
}
def materialize[T : c.WeakTypeTag]: c.Expr[DeepPrinter[T]] = {
val tpe = weakTypeOf[T]
val (names, types) = fields(tpe).unzip
// change the package name to the correct one here!
val tree = q"""
new com.bla.bla.DeepPrinter[$tpe] {
def debugString(sep: String = "\n") = Seq(..$names).mkString(sep)
}
"""
c.Expr[DeepPrinter[T]](tree)
}
}

Nothing inferred for type parameter

How is it possible that type parameter in call to get[A] is Nothing in this snippet? What can I do to force a compiler to produce an error when get is called without explicit type parameter?
case class User(email: String)
object Hello {
def main(args: Array[String]): Unit = {
val store = new ObjectStore
store.get
}
}
class ObjectStore {
def get[A: Manifest]: Option[A] = {
println(manifest[A].toString())
None
}
}
Based on this blog post, the following should work:
#implicitNotFound("Nothing was inferred")
sealed trait NotNothing[-T]
object NotNothing {
implicit object notNothing extends NotNothing[Any]
implicit object `\n The error is because the type parameter was resolved to Nothing` extends NotNothing[Nothing]
}
class ObjectStore {
def get[T](implicit evManifest: Manifest[T], evNotNothing: NotNothing[T]): Option[T] = {
println(manifest[T].toString())
None
}
}
object X {
val oo = new ObjectStore().get[Any]
//fails to compile
//val o = new ObjectStore().get
}

why do implicits not trigger in this type dependent paths scenario

Let's say I define some type in a trait, that should implement some type class (like functor):
import cats.Functor
import cats.syntax.functor.toFunctorOps
trait Library {
type T[+A]
implicit val isFunctor: Functor[T]
}
Now, I want to use this library. The following works fine:
trait LibraryUser {
val l: Library
import l._
def use: T[Boolean] = {
val t: T[Int] = ???
t.map(_ => true)
}
}
But when using it in a method with a parameter instead, the import of the implicit isn't working (out commented line doesn't compile) and you have to write the implicit for yourself instead:
object LibraryUser1 {
def use(l: Library): l.T[Boolean] = {
import l._
val t: T[Int] = ???
//t.map(_ => true)
toFunctorOps(t)(isFunctor).map(_ => true)
}
}
Why is this the case / what can be done against it.
This has previously been filed as a bug, specifically SI-9625. Implicits values that are path-dependent and return higher-kinded types fail to resolve. Here is a simplified example using the standard library:
trait TC[F[_]]
trait Foo {
type T[A]
implicit val ta: TC[T]
}
object Bar {
def use(foo: Foo) = {
import foo._
implicitly[TC[T]] // fails to resolve, but `implicitly[TC[T]](ta)` is fine
}
}
Sadly, even the most obvious use of the implicit fails:
object Bar {
def use(foo: Foo) = {
implicit val ta: TC[foo.T] = null
implicitly[TC[foo.T]] // nope!
}
}

Could not find implicit value for parameter x

Just when I thought I understood the basics of Scala's type system... :/
I'm trying to implement a class that reads the contents of a file and outputs a set of records. A record might be a single line, but it could also be a block of bytes, or anything. So what I'm after is a structure that allows the type of Reader to imply the type of the Record, which in turn will imply the correct Parser to use.
This structure works as long as MainApp.records(f) only returns one type of Reader. As soon as it can return more, I get this error:
could not find implicit value for parameter parser
I think the problem lies with the typed trait definitions at the top, but I cannot figure out how to fix the issue...
// Core traits
trait Record[T]
trait Reader[T] extends Iterable[Record[T]]
trait Parser[T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
trait TypeA
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
trait TypeB
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
// The "app"
object MainApp {
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File) = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
First off you must import the implicit object in order to use them:
import TypeA._
import TypeB._
That's not enough though. It seems like you're trying to apply implicits dynamically. That's not possible; they have to be found compile time.
If you import the objects as above and change the records so that the compiler finds the correct generic it will run fine:
def records(f: File) = new FileReader[TypeA](f)
But then it may not be what you were looking for ;)
The problem is that the return type of your records method is basically FileReader[_] (since it can return either FileReader[TypeA] or FileReader[TypeB]), and you don't provide an implicit argument of type Parser[Any]. If you remove the if-expression the return type is inferred to FileReader[TypeA], which works fine. I'm not sure what you're trying to do, but obviously the compiler can't select implicit argument based upon a type that is only known at runtime.
1) Using type with implicit inside as type parameter - doesn't bind this implicit to the host type, to do this change objects to the traits and mix them instead of generalizing (type-parametrizing):
def records(f: File) = {
if(true)
new FileReader(f) with TypeA
else
new FileReader(f) with TypeB
}
2) The parser should be in scope of function that calls parse. So you may try smthg like that:
def process(f: File) = {
val reader = records(f);
import reader._
reader foreach { r => parse(r) }
}
PlanB) Simpler alternative is to define type-parameter specific implicit methods inside the AppMain (or some trait mixed in), but it will work only if TypeA/TypeB is known on compile time, so records method can return concrete type:
implicit class TypeAParser(r: Record[TypeA]) {
def parse: Option[Int] = ???
}
implicit class TypeBParser(r: Record[TypeB]) {
def parse: Option[Int] = ???
}
def process[T <: TypeAorB](f: File) =
records[T](f).foreach(_.parse)
def recordsA[T <: TypeAorB](f: File) = new FileReader[T](f)
Here is, I think, the full set of modifications you need to do to get where I think you want to go.
import scala.io.Source
import java.io.File
import reflect.runtime.universe._
// Core traits
trait Record[+T]
trait Reader[+T] extends Iterable[Record[T]]
trait Parser[-T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations [unmodified]
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
sealed trait Alternatives
case class TypeA() extends Alternatives
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
case class TypeB() extends Alternatives
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
class ParseAlternator(parserA: Parser[TypeA], parserB: Parser[TypeB]) extends Parser[Alternatives] {
def parse(r: Record[Alternatives]): Option[Int] = r match {
case x: Record[TypeA #unchecked] if typeOf[Alternatives] =:= typeOf[TypeA] => parserA.parse(x)
case x: Record[TypeB #unchecked] if typeOf[Alternatives] =:= typeOf[TypeB] => parserB.parse(x)
}
}
object ParseAlternator {
implicit def parseAlternator(implicit parserA: Parser[TypeA], parserB: Parser[TypeB]): Parser[Alternatives] = new ParseAlternator(parserA, parserB)
}
// The "app"
object MainApp {
import ParseAlternator._
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File): Reader[Alternatives] = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
The gist of it is: all of this would be completely classsical if only your parse instance did not have to pattern-match on a generic type but dealt directly with an Alternative instead.
It's this limitation (inherited from the JVM) that scala can't properly pattern-match on an object of a parametric type that requires the reflection & typeOf usage. Without it, you would just have type alternatives for your content (TypeA, TypeB), which you would add to a sealed trait, and which you would dispatch on, in an implicit that produces a Parser for their supertype.
Of course this isn't the only solution, it's just what I think is the meeting point of what's closest to what you're trying to do, with what's most idiomatic.

implicit value not applied in scope

i'm trying to import a implicit Write declaration from an embedded object into a function that produces a JSON object based on a set of case classes.
case class TestModel(test:String)
object TestModel {
def manyToJSON(models: List[TestModel]) = {
import writes.micro
Json.toJson(models)
}
object writes {
implicit val micro = Json.writes[TestModel]
}
}
unfortunately, the scala compiler complains:
No Json serializer found for type List[models.TestModel]. Try to implement an implicit Writes or Format for this type.
the fun part is, if i'm using the write object as a pure expression within the method, its working.
object TestModel {
def manyToJSON(models: List[TestModel]) = {
import writes.micro
writes.micro
Json.toJson(models)
}
object writes {
implicit val micro = Json.writes[TestModel]
}
}
how would i have to change my code to have the implicit in scope?
the reason case class implicit is not working is that it is just a definition not value. Use case object will solve this issue like object. Consider this code:
object MainClass {
def main(args: Array[String]) {
TestModel.manyToJSON(Nil)
}
}
case class TestModel(test:String)
object TestModel {
def manyToJSON(models: List[TestModel]) = {
import writes._
def print(implicit x: Int) = {
println(x)
}
print // print 3
}
object writes {
implicit val x: Int = 3
//implicit val x = 3 //compilation error
}
}