【问题标题】:Stuck on writing a polymorphic transpose function that accepts and returns RDDs of either Arrays or Seqs/Vectors坚持编写一个多态转置函数,该函数接受并返回数组或序列/向量的 RDD
【发布时间】:2019-10-09 18:57:01
【问题描述】:

我正在重构一个与 Spark 接口的 Scala 库,以便在有意义的地方使用 Vectors。我想提供直接与 Spark 接口的函数,能够使用数组或向量。这些函数之一是转置函数。然而,我似乎无法获得正确的类型签名以使类型推断起作用。

我已尝试以以下方式定义函数签名,但这似乎不起作用,而是在我以字符串向量 RDD 为例运行测试时给我以下有关类型推断的消息。

 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)

【问题讨论】:

    标签: scala apache-spark types type-inference


    【解决方案1】:

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

    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]TString.

    *您实际上可以验证这一点:

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

    【讨论】:

    • 谢谢,这对向量很有效,但数组显然不符合预期的方法签名。我的理解是 Predefs 中存在从 Array 到 Seq 子类型的隐式转换,但在这里似乎并不适用。我还尝试向函数添加一个隐式参数以尝试在此提示编译器((implicit conv: Abs =&gt; Seq[T]) 并在函数签名中将 IndexedSeq 更改为 Seq),但这仍然不符合方法参数范围。
    猜你喜欢
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 2017-01-11
    • 1970-01-01
    相关资源
    最近更新 更多