Reputation: 2062
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
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