ScalaのOrdering
の形質が反則でない理由はありますか?動機付けの例が続きます。スカラ:規則の逆順を注文する
注文したインサートを実行したいとします。私はタイプA
のスーパータイプを受け入れるOrdering
を持って、署名ここ
def insert[A, B >: A](list: List[A], item: A)(implicit ord: Ordering[B]): List[A]
と機能を有していてもよいです。私はこれが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
}
すべての作品を定義した場合。
私の目標を達成する他の方法はありますか?
EDIT:
私の現在のソリューションは、List[CodeTree]
を扱うときに正常に動作
def insert[A](list: List[A], item: A)(implicit ord: Ordering[A]): List[A]
として、インサートを定義することです。私はまた、(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]
インスタンスに対して暗黙のファクトリ関数を定義しています。 、これらの方法は反変であることから、それを防ぐため、現在のAPIで
最も具体的な注文を見つけることができないタイプ推論に関連する技術的な問題のようです。詳細はhttp://scala-programming-language.1934581.n4.nabble.com/Contravariant-Ordering-T-java-util-Comparator-and-uncheckedVariance-td1955224.htmlを参照してください。 – Impredicative
@Impredicative厄介な回避策で投稿を編集しました。 –