2014-10-27 39 views
0

我想实现一个distinctBy方法,我可以很容易地为Seq做到这一点,但作为冒险家伙,我想尝试做一些更通用的事情。了解TraversableOnce和子类型

def distinctBy[A, B, M[_] <: TraversableOnce[_]](xs: M[A])(f: A => B)(implicit cbf: CanBuildFrom[M[A], A, M[A]]): M[A] = { 

    val seen = mutable.Set.empty[B] 
    val builder = cbf(xs) 

    for (x <- xs) { 
     val k = f(x) 
     if (!seen.contains(k)) { 
      seen += k 
      builder += x 
     } 
    } 

    builder.result() 
} 

这里的基本直觉是我映射到一个类型,并保持一组的的轨道,而不是原来的集合中的元素定义的平等。所以我可以拿一组不同的元组来比较左边的元素,或者右边的元素。

即使我切换到只使用forall,我也无法获得此编译,因为它似乎并不认为xs具有TraversableOnce上定义的任何方法,即使存在子类型关系。我显然在这里错过了一些非常基本的东西,并会很感激任何帮助。

回答

2

您可能希望限制为M[X] <: TraversableOnce[X]_是特别的,并且您目前的签名只会知道M[A] <: TraversableOnce[_],而您想要M[A] <: TraversableOnce[A]

您错过了一个右大括号,这可能很重要。

你得到了什么确切的编译错误?

+0

这完全是问题所在。我已经从'Future.traverse'的实现中复制了'M [_]'malarky。这似乎合乎逻辑。我想要一种类型'* - > *',然后在签名中明确指出xs是'M [A]类型'。确切的错误是: – 2014-10-27 20:42:41

+0

[错误] /src/main/scala/com/sphonic/spark/common/RequiredFacts.scala:185:缺少参数类型 [错误](x < - xs){0} {0} {error} – 2014-10-27 20:50:04