2014-10-27 59 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