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

How to define implicit class for Traversable with CanBuildFrom?

我正在尝试通过 implicit class.

Traversable 特征添加一些方法

但我有点迷失了 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)
}

失败并出现错误:

Error:(21, 59) type mismatch;
found : scala.collection.generic.CanBuildFrom[Repr,A,That]
required: scala.collection.generic.CanBuildFrom[Traversable[A],A,That]
traversable.map{ a => println(name + ": " + a); a }(bf) ^

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

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

您必须使用 TraversableLike 和更高种类的类型才能使类型推断器满意并使其与 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],...]

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