【问题标题】:Workaround for Scala RDD not being covariantScala RDD 的解决方法不是协变的
【发布时间】:2014-07-11 20:24:24
【问题描述】:

我正在尝试编写一个函数来操作 RDD[Seq[String]] 对象,例如:

def foo(rdd: RDD[Seq[String]]) = { println("hi") }

无法对 RDD[Array[String]] 类型的对象调用此函数:

val testRdd : RDD[Array[String]] = sc.textFile("somefile").map(_.split("\\|", -1))
foo(testRdd)

->
error: type mismatch;
found   : org.apache.spark.rdd.RDD[Array[String]]
required: org.apache.spark.rdd.RDD[Seq[String]]

我猜这是因为 RDD 不是协变的。

我已经尝试了一堆 foo 的定义来解决这个问题。只有其中一个已编译:

def foo2[T[String] <: Seq[String]](rdd: RDD[T[String]]) = { println("hi") }

但还是坏了:

foo2(testRdd)


->
<console>:101: error: inferred type arguments [Array] do not conform to method foo2's type
parameter bounds [T[String] <: Seq[String]]
          foo2(testRdd)
          ^
<console>:101: error: type mismatch;
found   : org.apache.spark.rdd.RDD[Array[String]]
required: org.apache.spark.rdd.RDD[T[String]]

知道如何解决这个问题吗?这一切都发生在 Spark shell 中。

【问题讨论】:

  • 从您的示例中无法完全清楚为什么 foo 的这个定义不够:def foo[T](rdd: RDD[T])。另外,请注意ArraySeq 之间没有子类型关系。在Predef 中只有一个隐式转换,它允许我们在需要Seq 的地方使用Array。来源:scala-lang.org/api/2.11.1/index.html#scala.Array
  • @IonuțG.Stan foo(new RDD(...) 会工作,但val rdd: RDD[Array[String]] = ...; foo(rdd) 不会。不存在转换RDD[Array[String]] =&gt; RDD[Seq[String]]

标签: scala types covariance apache-spark


【解决方案1】:

为此,您可以使用view bound

Array 不是Seq,但可以查看Seq

def foo[T <% Seq[String]](rdd: RDD[T]) = ???

&lt;% 表示T 可以被视为Seq[String],因此每当您在T 上使用Seq[String] 方法时,T 将被转换为Seq[String]

为了将Array[A] 视为Seq[A],范围内需要一个隐式函数,可以将Arrays 转换为Seqs。正如 Ionuț G. Stan 所说,它存在于scala.Predef

【讨论】:

    猜你喜欢
    • 2020-06-26
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    相关资源
    最近更新 更多