TraversableOnce 上的 Scala 2.10 隐式函数应该接受数组但不接受

Scala 2.10 implicit function over TraversableOnce should accept an Array but doesn't

我写了一个简单的隐式函数:mkString() 的一个版本,它的工作方式相同,但如果在任何要连接的参数中找到分隔符,则会抛出错误。我想让它适用于所有类似序列的东西,所以我声明如下:

object SafeMkString {
  implicit class SafeMkStringHelper[T](values: TraversableOnce[T]) {
    def safeMkString(sep: String) = {
      values.map { v =>
        val asStr = v.toString
        if (asStr.contains(sep))
          throw new IllegalArgumentException("Value %s in %s contains separator %s" format
            (asStr, values, sep))
        else
          asStr
      }.mkString(sep)
    }
  }
}

这对大多数对象都适用,但在 Scala 2.10 中使用 Array[String] 类型的东西会失败。这是因为 Scala 中的数组只是 Java 数组的别名,而不是从 TraversableOnce 继承。但是,有一个从 ArrayWrappedArray 的隐式转换, 继承自 TraversableOnce。 Scala 中是否有一些规则不允许从 A -> B 然后从 B -> C 进行隐式转换?除了手动创建另一个显式应用 Array[T] 中的 safeMkString 的隐式 class 之外,有什么方法可以使它正常工作?

第 1 个问题的回答来自 Programming in Scala (1st Edition),第 21 章:

One-at-a-time Rule: Only one implicit is tried. The compiler will never rewrite x + y to convert1(convert2(x)) + y. Doing so would cause compile times to increase dramatically on erroneous code, and it would increase the difference between what the programmer writes and what the program actually does. For sanity's sake, the compiler does not insert further implicit conversions when it is already in the middle of trying another implicit. However, it's possible to circumvent this restriction by having implicits take implicit parameters, which will be described later in this chapter.

受@jwvh 回答(尤其是引用的最后一行)的启发,我想出了以下内容:

implicit class CanBeTraversable[A, T](a: A)(implicit ev: A => TraversableOnce[T]){
  def safeMkString(sep: String) = {
    val values = ev(a)
    ... //put here the body of your method
}

它所做的是从任何类型 A 隐式转换为某些 TTraversableOnce[T] 的隐式转换。这适用于 List,因为 =:= : List[T] => List[T] 是隐式转换(另外,因为 Function1 在其第二个参数 Function1[List[T], List[T]] <: Function1[List[T], TraversableOnce[T]] 中是协变的)。它也适用于 Array 因为它隐式转换为 WrappedArray.