具有注入器和实例化的scala动态多态性

时间:2018-12-10 22:31:58

标签: scala generics shapeless type-level-computation

我了解到scala generic type hierarchy with different attribute name带有提取器的动态多态性可以解决部分问题。但是,我还了解到,猫,小猫和无形状的猫可能是通往清洁解决方案的道路。不幸的是,我还不熟悉任何一个。尝试从之前的示例构建时,我意识到提取器是不够的。

如何创建注射器?也许甚至没有形状?并动态实例化拟合对象。

Beow是使用提取器的更完整示例,并描述了我的编译错误:

import org.apache.spark.sql.{Dataset, SparkSession}

sealed trait Db {
  def db: String

  def table: String
}

case class DataSource(override val db: String,
                      override val table: String)
  extends Db


trait Feed extends BaseConfiguration

trait FooFeedConfiguration extends Feed {
  def fooFeed: DataSource
}

trait FeedDataSourceExtractor[F <: Feed] {
  def extract(feedDs: F): DataSource
}

implicit val cellFeedEx = new FeedDataSourceExtractor[FooFeedConfiguration] {
  override def extract(feedDS: FooFeedConfiguration) = feedDS.fooFeed
}

trait BaseConfiguration {
  def applicationName: String
}

trait SparkDatasetProvider[T <: Product, C <: BaseConfiguration] {

  def provide(spark: SparkSession, c: C): Dataset[T]
}

def myFunction[T <: Product, F <: Feed, feedProvider <: SparkDatasetProvider[T, F]](spark: SparkSession, c: F)(implicit feedEx: FeedDataSourceExtractor[F]): Dataset[T] = {
  val dataSourceWithInterval = feedEx.extract(c)
  //FooFeedProvider.provideAndFilter(
  feedProvider.provide( // TODO why does this not compile.
    spark,
    //new FooFeedConfiguration  {
    new F {
      override val applicationName = c.applicationName
      override val feed // TODO need some kind of injector
      DataSource(dataSourceWithInterval.db, // real code performs some fancy logic here (on other attribute values)
        dataSourceWithInterval.table)
    }
  )
}

final case class FooFeed(foo: Int, bar: String)

object FeedProvider extends SparkDatasetProvider[FooFeed, FooFeedConfiguration] {
  override def provide(spark: SparkSession, c: FooFeedConfiguration) = {
    import spark.implicits._
    spark.sql(s"select * from ${c.fooFeed.db}.${c.fooFeed.table}").as[FooFeed]
  }
}

myFunction[FooFeed, FooFeedConfiguration, FeedProvider[FooFeed, FooFeedConfiguration]]()
// cant call FeedProvider
// all these type parameters (duplicated) seem to be not elegant. Is there a better way?

0 个答案:

没有答案