我正在重构一个与火花接口的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])
}
由于Abs
是IndexedSeq[T]
的子类型,Abs with IndexedSeq[T]
和Abs
或多或少是等效的(*(,只有现在编译器才能推断Abs
是Vector[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>