如何使用CanBuildFrom为Traversable定义隐式类?

时间:2016-04-09 10:10:59

标签: scala scala-collections

我正试图通过Traversable拉皮条为implicit class特征添加一些方法。

但我有点CanBuildFrom特质迷失了。请考虑以下事项:

implicit class TraversableExt[+A, +Repr <: Traversable[A]](traversable: Repr) {
  def debug[That](name: String)(implicit bf: CanBuildFrom[Repr, A, That]): That =
    traversable.map{ a => println(name + ": " + a); a }(bf)
}

此操作失败并显示错误:

  

错误:(21,59)类型不匹配;
    发现:scala.collection.generic.CanBuildFrom [Repr,A,That]
    必需:scala.collection.generic.CanBuildFrom [Traversable [A],A,That]
        traversable.map {a =&gt; println(name +“:”+ a); a}(bf)                                                             ^

我猜是因为Repr中的CanBuildFrom[-Repr, -Elem, +To]是逆变的,因此Repr上限Traversable[A]可能不起作用。

但总的来说,我很失落。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:6)

您必须使用TraversableLike及更高级别的kinded类型才能使类型推断器满意并使其与CanBuildFrom一起使用:

implicit class TraversableExt[A, C[X] <: TraversableLike[X, C[X]]](traversable: C[A]) {
  def debug[That](name: String)(implicit bf: CanBuildFrom[C[A], A, That]): That =
    traversable.map{ a => println(name + ": " + a); a }(bf)
}

编译器现在能够正确推断集合的类型C[A],而不是一般地查找CanBuildFrom[Traversable[A],...]

根据经验,当您想要返回与传入的集合类相同的集合类时,您必须使用*Like