斯卡拉的Ordering
特質沒有任何原因是不會逆轉的嗎?一個激勵的例子如下。斯卡拉:排序反轉
假設我想執行一個有序插入。我可以具有功能與簽名
def insert[A, B >: A](list: List[A], item: A)(implicit ord: Ordering[B]): List[A]
在這裏,我有接受超級類型A
類型的Ordering
。我想這在你處理case classes
時很有用。例如:
abstract class CodeTree
case class Fork(left: CodeTree, right: CodeTree, chars: List[Char], weight: Int) extends CodeTree
case class Leaf(char: Char, weight: Int) extends CodeTree
def weight(tree: CodeTree): Int
def chars(tree: CodeTree): List[Char]
implicit object CodeTreeOrdering extends Ordering[CodeTree] {
def compare(a: CodeTree, b: CodeTree): Int = weight(a) compare weight(b)
}
我希望我的插入功能與類型List[CodeTree]
,List[Leaf]
或List[Fork]
工作。但是,由於Ordering
不是逆變,我需要爲每個case
定義隱式Orderings
。
如果我定義
trait MyOrdering[-A] {
def compare(a: A, b: A): Int
}
一切正常。
有沒有其他辦法可以實現我的目標?
編輯:
我目前的解決方案是定義插入物
def insert[A](list: List[A], item: A)(implicit ord: Ordering[A]): List[A]
與List[CodeTree]
打交道時,工作正常。我還定義(由scalaz庫的啓發):
trait Contravariant[F[_]] {
def contramap[A, B](r: F[A], f: B => A): F[B]
}
implicit object OrderingContravariant extends Contravariant[Ordering] {
def contramap[A, B](r: Ordering[A], f: B => A) = r.on(f)
}
implicit def orderingCodeTree[A <: CodeTree]: Ordering[A] =
implicitly[Contravariant[Ordering]].contramap(CodeTreeOrdering, identity)
我定義Ordering[A <: CodeTree]
情況下,一個隱含的工廠函數。
看起來像是一個與類型推理未能找到最具體排序有關的技術問題。有關詳細信息,請參閱http://scala-programming-language.1934581.n4.nabble.com/Contravariant-Ordering-T-java-util-Comparator-and-uncheckedVariance-td1955224.html。 – Impredicative
@Impredicative我用一個討厭的解決方法編輯帖子。 –