坚持编写接受和返回数组或seq/vectors的RDD的多态性转置函数



我正在重构一个与火花接口的scala库,以便在有意义的地方使用向量。我想提供与Spark与数组或向量一起工作的能力直接接口的功能。这些功能之一是转置函数。但是,我似乎无法获得制作类型推理工作的类型签名。

我尝试通过以下方式定义函数签名,但这似乎不起作用,而是在以字符串vector rdds作为示例进行测试时给我以下有关类型推理的消息。

 def transpose[T, Abs <: IndexedSeq[T] : ClassTag](rdd: RDD[Abs]): RDD[Abs] = {
​
  rdd
   .zipWithIndex // give the columns an index
   .flatMap{
    case (row, row_idx) => row.zipWithIndex.map{ // give the rows an index
     case (el, col_idx) => (col_idx, (row_idx, el)) // each element now has a column and row index
    }
   }
   .groupBy(_._1)
   .sortBy(_._1)
   .map{ case (_, els) => els.map(_._2).toIndexedSeq.sortBy(_._1) }
   .map( row => row.map(_._2))
   .map(_.asInstanceOf[Abs])
 }
Error:(26, 5) inferred type arguments [Nothing,scala.collection.immutable.Vector[String]] do not conform to method transpose's type parameter bounds [T,Abs <: IndexedSeq[T]]
    transpose(subset)
Error:(26, 15) type mismatch;
 found   : org.apache.spark.rdd.RDD[scala.collection.immutable.Vector[String]]
 required: org.apache.spark.rdd.RDD[Abs]
    transpose(subset)

编译器仅设法推断出出现在"值参数列表"中的类型参数(或在某些情况下,返回类型(。通常在这样的情况下有效的技巧是:

def transpose[T, Abs <: IndexedSeq[T] : ClassTag](rdd: RDD[Abs with IndexedSeq[T]]): RDD[Abs] = {
  rdd
   .zipWithIndex // give the columns an index
   .flatMap{
    case (row, row_idx) => row.zipWithIndex.map{ // give the rows an index
     case (el, col_idx) => (col_idx, (row_idx, el)) // each element now has a column and row index
    }
   }
   .groupBy(_._1)
   .sortBy(_._1)
   .map{ case (_, els) => els.map(_._2).toIndexedSeq.sortBy(_._1) }
   .map( row => row.map(_._2))
   .map(_.asInstanceOf[Abs])
 }

由于AbsIndexedSeq[T]的子类型,Abs with IndexedSeq[T]Abs或多或少是等效的(*(,只有现在编译器才能推断AbsVector[String]T是CC_7。

*您实际上可以验证以下内容:

scala> implicitly[Vector[String] =:= (Vector[String] with IndexedSeq[String])]
res3: =:=[Vector[String],Vector[String] with scala.collection.immutable.IndexedSeq[String]] = <function1>

最新更新