通常采用类型并返回相同类型的函数

时间:2012-04-04 21:29:33

标签: scala generics collections functional-programming type-theory

我很难理解为什么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的任何实现并获得相同类型的退出。这可能吗?

2 个答案:

答案 0 :(得分:14)

map上的Iterable方法会返回Iterable,因此即使TIterable的子类,它的map方法也会返回Iterable

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

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

然而,这也无效,因为没有信息让T上的地图生成另一个T。例如,将BitSet映射到String不会产生BitSet。所以我们需要其他东西:教导如何从T构建T,其中映射元素的类型为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", "") }

答案 1 :(得分: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", "") }