3

という名前の ScalaIDE ワークシートを作成した後、test.WsTemp以下のコードを書きましたが、 trait の 1 行で 3 つのエラーが発生していますEnum

  1. scala.math.Ordering[U]トレイトで順序付けされたメソッドで始まる型の暗黙的な展開の発散LowPriorityOrderingImplicits
  2. 暗黙的Orderingに定義されていませんU
  3. メソッド sorted の十分な引数がありません: (implicit ord: scala.math.Ordering[U])List[U]、指定されていない値パラメータord

Val明らかなextendsであるため、なぜこれが機能しないのOrdered[Val]ですか?

object WsTemp {
  trait Val extends Ordered[Val] {
    val id: Int
    val name: String
    final def compare(that: Val) = this.id - that.id
    override def toString: String = name
  }

  trait Enum[U <: Val] {
    protected def init: Set[U]
    val all = init
    val allOrdered = all.toList.sorted       // <-- Receiving error here
    val byId = all.map(x => (x.id, x)).toMap
    val byName = all.map(x => (x.name, x)).toMap

    def apply(id: Int) = byId.get(id)
    def apply(name: String) = byName.get(name)
  }

  sealed class Value(val id: Int, val name: String) extends Val
  object Suit extends Enum[Value] {
    override def init: Set[Value] = //Set()
      Set(
          new Value(0, "Spade")
        , new Value(1, "Club")
        , new Value(2, "Diamond")
        , new Value(3, "Heart")
      )
    val Spade = Suit.byId(0)
    val Club = Suit.byId(1)
    val Diamond = Suit.byId(2)
    val Heart = Suit.byId(3)
  }

  val all = Suit.all
  val allOrdered = Suit.allOrdered
  val byId = Suit.byId
  val byName = Suit.byName
  val spade = Suit.Spade
}
4

2 に答える 2

4

Orderingとは両方とも不変なので、が のサブタイプであるOrderedという事実は(関係 で表されるように) がとして使用できることを意味しません。したがって、extendsという事実は暗黙のうちに を取得することを意味しますが、これは に関しては何も意味しません。UValU <: ValOrdering[Val]Ordering[U]ValOrdered[Val]Ordering[Val]Ordering[U]

したがって、コンパイラが型の暗黙の値を見つけることができないと文句を言うのは正しいことOrdering[U]です (これは の呼び出しに必要ですsorted)。

Orderedこの問題は、と で何が起こるかを模倣する小さなコード スニペットで簡単に説明できますOrdering

object WsTemp {
  trait MyOrdered[T]

  trait MyOrdering[T]
  object MyOrdering {
    implicit def toOrdering[A <% MyOrdered[A]]: MyOrdering[A] = new MyOrdering[A]{}
  }

  trait Val extends MyOrdered[Val]

  def test[T](implicit ord: MyOrdering[T]) {}

  trait Enum[U <: Val] {
    def callTest() { test[U] }
  }
}

次のエラーが発生します。

<console>:20: error: could not find implicit value for parameter ord: WsTemp.MyOrdering[U]
           def callTest() { test[U] }

しかし、makeMyOrderedMyOrdering共変の場合、これは問題なくコンパイルされます。

trait MyOrdered[+T]      
trait MyOrdering[+T]
...

明らかに、scala を変更したり、不変にしたりするOrderingことはできません。Ordered


ここで、問題を解決する 1 つの方法は、コードをVal拡張しないように配置することですOrdered[Val]が、代わりにfor を使用する実際の型(ここではOrdered[X]= )を拡張します。これは、 F-bounded polymorphismで実現できます。XOrderingXU

trait Val[Self<:Val[Self]] extends Ordered[Self] {
  //...
}

trait Enum[U <: Val[U]] {
  //...
}

sealed class Value(val id: Int, val name: String) extends Val[Value]
//...

Uは(以前の のサブVal[U]タイプOrdered[U]とは対照的に) のサブタイプである のサブタイプになり、に (暗黙的に) 渡される をOrdered[Val]暗黙的に取得するようになりました。問題が解決しました。Ordering[U]sorted

于 2013-02-24T23:42:49.120 に答える
1

Régis Jean-Gilles が言ったように、「Ordering と Ordered はどちらも invariant であるため、U が Val のサブタイプであるという事実 (関係 U <: Val で表される) は、Ordering[Val] を次のように使用できることを意味しません。したがって、Val が Ordered[Val] を拡張するという事実は、暗黙的に Ordering[Val] を取得することを意味しますが、これは Ordering[U] に関しては何も意味しません。」

これを修正する非常に簡単な方法は、ソートされたメソッドに使用する型を指定することです。交換:

  val allOrdered = all.toList.sorted 

と:

  val allOrdered = all.toList.sorted[Val] 
于 2013-12-16T13:40:35.997 に答える