user2726995
user2726995

Reputation: 2062

Could not Find Implicit parameter in scala typeclass

I am trying to create a type class based on the type data to load --

Here are the types:

trait DataSource
case class HDFSSource(path: String) extends DataSource
case class HiveTableSource(db: String, tbl: String) extends DataSource

here is the trait

trait Loader[A, B, C] {
  //Any Spark loader requires
  // A -> Input Type
  // B -> Output Type
  // C -> some type of implicit context provided by the compiler from the sourounding environemnt..
  def load(input: A)(implicit context: C): B

And here is the implementation:

object Loader {
  implicit object HiveLoader extends Loader[HiveTableSource, DataFrame, HiveContext] {
    def load(source: HiveTableSource)(implicit hc: HiveContext): DataFrame = {
      val db = source.db
      val tbl = source.tbl
      val df =  hc.sql(s"select * from $db.$tbl")
      df
    }
  }
  def loadDataSource[A: Loader, B, C](d: A) = implicitly[Loader[A,B,C]].load(d)

The compiler complains that it can not find implicit evidence for parameter, specificly in the "implicitly[A.B.C]:

The goal is to have a typeclass that has different behavior for each type, and also use a different context (implicitly provided by the environment)

Upvotes: 0

Views: 358

Answers (1)

Armando Ramirez
Armando Ramirez

Reputation: 51

def loadDataSource[A, B, C](d: A)(implicit ldr: Loader[A,B,C], context: C): B = ldr.load(d)

I did not try compiling it myself but I'm fairly sure that would work.

loadDataSource[A: Loader, B, C](d: A) is desugared to loadDataSource[A, B, C](d: A)(implicit ev: Loader[A]), which doesn't work here because Loader takes 3 type parameters. So you have to explicitly annotate the implicit parameter instead of using a context bound.

In order to call Loader's load method, an implicit C must be provided. That's why I added the additional context: C implicit parameter.

Upvotes: 4

Related Questions