更高的kinded类型和WrappedString

时间:2013-05-16 14:30:59

标签: scala

为什么这段代码适用于Lists和Vectors但是WrappedString失败了?

implicit class TraversableExt[A, CC[A] <: TraversableLike[A, CC[A]]](lst: CC[A]) {
  def filterPairs(f: (A, A) => Boolean)(implicit bf: CanBuildFrom[CC[A], A, CC[A]]): CC[A] = {
    def filterPairs(lst: TraversableLike[A, CC[A]], result: Builder[A, CC[A]]): CC[A] = {
      if(lst.isEmpty) result.result
      else if(lst.tail.isEmpty) (result += lst.head).result
      else if(!f(lst.head, lst.tail.head)) filterPairs(lst.tail, result)
      else filterPairs(lst.tail, result += lst.head)
    }
    filterPairs(lst, bf())
  }
}
println(List(1,2,2,3).filterPairs(_ != _))

如果我明确地调用方法

println(TraversableExt(new WrappedString("hi thhere")).filterPairs(_ != _))

我收到此错误

error: inferred type arguments [Char,scala.collection.AbstractSeq] do not conform to method TraversableExt's type parameter bounds [A,CC[A] <: scala.collection.TraversableLike[A,CC[A]]]
println(TraversableExt(new WrappedString("hi thhere")).filterPairs(_ != _))

1 个答案:

答案 0 :(得分:3)

[A, CC[A] <: TraversableLike[A, CC[A]]](lst: CC[A])

WrappedStringTraversableLike[Char, WrappedString]WrappedString不带任何类型参数,因此它不能是CC[A]

您可以使用IsTraversableOnce

import collection.generic.{IsTraversableOnce, CanBuildFrom}
import collection.GenTraversableOnce

class TraversableExt[A, Repr](val lst: GenTraversableOnce[A]) {
  def filterPairs[That](f: (A, A) => Boolean)(implicit cbf: CanBuildFrom[Repr, A, That]): That = {
    val b = cbf()
    var prev: Option[A] = None
    for ( e <- lst ) {
      for {
        pr <- prev
        if f(pr, e)
      } b += pr
      prev = Some(e)
    }
    b ++= prev
    b.result
  }
}
implicit def toTraversableExt[Repr](coll: Repr)(implicit tr: IsTraversableOnce[Repr]) =
  new TraversableExt[tr.A, Repr](tr.conversion(coll))

scala> List(1,2,2,3).filterPairs(_ != _)
res0: List[Int] = List(1, 2, 3)

scala> "abbcccddddeaa".filterPairs(_ != _)
res1: String = abcdea