Динамически приведенный кадр данных искры к набору данных кортежа (String, _ <: Product) - PullRequest
3 голосов
/ 10 ноября 2019

Я столкнулся со специфической проблемой при работе со свечой, я не совсем уверен, что происходит, было бы здорово, если кто-то может помочь. Моя проблема в том, чтобы иметь функцию, аналогичную приведенной ниже, которая преобразует кадры данных в наборы данных некоторого типа, что решается во время выполнения. Мне нужно работать с наборами данных, потому что базовые классы дел имеют некоторые аннотации, которые я хотел бы использовать.

 def ret(spark: SparkSession, dss: DataFrame, typ: String): Dataset[_ <: Product] = {
    import spark.implicits._
    typ match {
      case "t1" => dss.as[T1]
      case "t2" => dss.as[T2]
    }

  }

Я могу привести кадр данных к набору данных с помощью следующего вызова функции val ds = ret(spark,dataframe,"t1")

Все работает хорошо с этой функцией, теперь я хочу расширить существующую функцию, чтобы вернуть Dataset[(String,_<:Product)], поэтому я изменяю свою функцию следующим образом:

 def ret(spark: SparkSession, dss: DataFrame,typ: String):Dataset[(String,_ <: Product)] = {
    import spark.implicits._
    typ match {
      case "t1" => dss.as[(String,T1)]
      case "t2" => dss.as[(String,T2)]
    }
  }

Это дает мне ошибку компиляции, говоря:тип (String,T1), не соответствует ожидаемому типу (String,_<:Product). Что на самом деле здесь происходит? Есть идеи, как я могу это исправить? Любые советы будут высоко оценены!

Спасибо большое!

Обновление: Верхняя граница <: Продукт относится к scala.Product и T1, T2 могут быть любыми классами случаев, например, </p>

case class T1(name: String, age: Int)

case class T2(name: String, max: Int, min: Int)

Но это может бытьдействительно что-нибудь

1 Ответ

3 голосов
/ 10 ноября 2019

Общий супертип Dataset[(String, T1)] и Dataset[(String, T2)] - это не Dataset[(String,_ <: Product)], а более сложный экзистенциальный тип

Dataset[(String, T)] forSome { type T <: Product }

Dataset[(String,_ <: Product)] также действительно экзистенциальный тип,но другой;это сокращение для

Dataset[(String, T) forSome { type T <: Product }]

Обратите внимание, что для использования Dataset[(String, T)] forSome { type T <: Product } без предупреждений необходимо добавить import scala.language.existentials (и эти типы будут удалены в Scala 3 ).

РЕДАКТИРОВАТЬ: Я думал, что то, что я проверил, будет достаточно, но очевидно, что вывод типа здесь терпит неудачу, и я действительно не понимаю, почему.

def ret(spark: SparkSession, dss: DataFrame, typ: String): Dataset[(String, T)] forSome { type T <: Product } = {
  import spark.implicits._
  typ match {
    case "t1" => dss.as[(String,T1)]: (Dataset[(String, T)] forSome { type T <: Product })
    case "t2" => dss.as[(String,T2)]: (Dataset[(String, T)] forSome { type T <: Product })
  }
}

делает компилировать какожидается. Вы можете извлечь псевдоним типа, чтобы избежать дублирования:

type DatasetStringT = Dataset[(String, T)] forSome { type T <: Product }

def ret(spark: SparkSession, dss: DataFrame, typ: String): DatasetStringT = {
  import spark.implicits._
  typ match {
    case "t1" => dss.as[(String,T1)]: DatasetStringT 
    case "t2" => dss.as[(String,T2)]: DatasetStringT 
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...