6

我很难理解为什么 Scala 编译器对这个函数定义不满意:

def trimNonWordCharacters[T <: Iterable[String]](items: T): T =
     items map { _.replaceAll("\\W", "") }

这是REPL输出:

scala> def trimNonWordCharacters[T <: Iterable[String]](items: T): T =
     items map { _.replaceAll("\\W", "") }
<console>:5: error: type mismatch;
 found   : Iterable[java.lang.String]
 required: T
       def trimNonWordCharacters[T <: Iterable[String]](items: T): T = items map { _.replaceAll("\\W", "") }

目标是传入 Iterable 的任何实现并获得相同类型的回退。这可能吗?

4

2 回答 2

14

mapon 方法Iterable返回一个Iterable,所以即使T是 的子类Iterable,它的方法map也会返回Iterable

为了更好地打字,你必须这样写:

import scala.collection.IterableLike
def trimNonWordCharacters[T <: Iterable[String]](items: T with IterableLike[String, T]): T =
     items map { _.replaceAll("\\W", "") }

但是,这也行不通,因为没有信息可以让地图T生成另一个T. 例如,将 a 映射BitSet到 aString不会导致 a BitSet。所以我们需要别的东西:教如何T从 a构建 a 的东西T,其中映射的元素是 type String。像这样:

import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
def trimNonWordCharacters[T <: Iterable[String]]
                         (items: T with IterableLike[String, T])
                         (implicit cbf: CanBuildFrom[T, String, T]): T =
     items map { _.replaceAll("\\W", "") }
于 2012-04-04T21:52:33.087 回答
0

[作为答案而不是评论输入,因为评论中的代码格式不正确]

@Daniel,感谢您的解释,我也发现它很有用。由于 Iterable 派生自 IterableLike,以下似乎也可以工作,并且稍微紧凑:

import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
def trimNonWordCharacters[T <: IterableLike[String, T]]
 (items: T)
 (implicit cbf: CanBuildFrom[T, String, T]): T =
 items map { _.replaceAll("\\W", "") }
于 2012-08-31T13:58:38.260 回答