2012-11-25 55 views
4

我試圖編寫一個函數,通過函數F(我將它稱爲F(S))來映射序列S,將結果值( F(S))與S,並分類由F(S)的結果,返回排序壓縮值(我希望代碼清除這件事,這是難以付諸文本)Scala函數,使用通用函數的映射對Seq進行排序

這裏是我當前的代碼:

def sortByAndReturnZippedMetric[S,M<:Ordering[AnyVal]](s:Seq[S], mapper:S=>M):Seq[(M,S)] = 
s.map(mapper).zip(s).sortBy(_._1) 

Scalac抱怨,雖然:

error: diverging implicit expansion for type scala.math.Ordering[M] 
starting with method comparatorToOrdering in trait LowPriorityOrderingImplicits 
s.map(mapper).zip(s).sortBy(_._1) 

          ^

我會很感激一些指引,以什麼可能是錯誤的...

回答

6

Orderingtype class,這意味着如果你要拍攝A以特定方式排列的事實,你只需把一個隱含的Ordering[A]的實例納入範圍 - 您沒有A延伸Ordering[A](或Ordering[AnyVal]等)。

這種方法的優點是,您可以使用特定類型的多個排序(儘管某個類型一次只能有一個隱式排序)。因此,例如,我可以寫:

scala> List(5, 2, 3, 1, 4).sorted 
res0: List[Int] = List(1, 2, 3, 4, 5) 

這裏隱含的排序爲整數(Ordering.Int)作爲隱含參數sorted,但我們也可以明確地傳遞不同的Ordering。例如,我們可以通過翻轉隱含創建一個新的排序:

scala> List(5, 2, 3, 1, 4).sorted(Ordering.Int.reverse) 
res1: List[Int] = List(5, 4, 3, 2, 1) 

在你的情況sortBy正在尋找一個Ordering[Ordering[AnyVal]],它不存在。您可以輕鬆地通過使用context bound,表明你需要一個排序爲M,而不必M解決這個問題擴展Ordering[AnyVal]

def sortByZipped[S, M: Ordering](s: Seq[S], mapper: S => M): Seq[(M, S)] = 
    s.map(mapper).zip(s).sortBy(_._1) 

或者你可以跳過語法糖和使用隱含參數:

def sortByZipped[S, M](s: Seq[S], mapper: S => M)(implicit o: Ordering[M]) = 
    s.map(mapper).zip(s).sortBy(_._1)(o) 

這與具有上下文綁定的版本完全相同。

+1

whoosh!這裏有很多事情我沒有意識到,但是你的答案已經被完整地解釋和記錄,所以這只是時間問題。這是真正的黃金 - 謝謝你讓我意識到我不知道的東西! –