scala SortedMaps の結合を形成するにはどうすればよいですか?
-
20-09-2019 - |
質問
(私は Scala nightlies を使用していますが、2.8.0b1 RC4 でも同じ動作が見られます。私は Scala の初心者です。)
私は2つを持っています SortedMap
組合を結成したいと思っています。使用したいコードは次のとおりです。
import scala.collection._
object ViewBoundExample {
class X
def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = {
a ++ b
}
implicit def orderedX(x: X): Ordered[X] = new Ordered[X] { def compare(that: X) = 0 }
}
ここでの考え方は、「暗黙の」ステートメントが意味するものです。 X
に変換できます Ordered[X]
s、そしてそれを組み合わせるのは理にかなっています SortedMap
別のことに SortedMap
, 、単なる地図ではなく。
コンパイルすると、次のようになります
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac -versionScala compiler version
2.8.0.Beta1-RC4 -- Copyright 2002-2010, LAMP/EPFL
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac ViewBoundExample.scala
ViewBoundExample.scala:8: error: type arguments [ViewBoundExample.X] do not
conform to method ordered's type parameter bounds [A <: scala.math.Ordered[A]]
a ++ b
^
one error found
その型パラメータのバインドがあれば、私の問題は解決するようです [A <% scala.math.Ordered[A]]
, 、 それよりも [A <: scala.math.Ordered[A]]
. 。残念ながら、「ordered」メソッドがどこに存在するのかさえわかりません。誰か追跡を手伝ってくれませんか?
それができない場合、2つの結合を生み出すために私は何をするつもりですか SortedMap
は?結合の戻り値の型を削除した場合 (または次のように変更した場合) Map
)すべてが正常に動作します --- しかし、そうすると、返品がソートされることは当てにできません。
解決
現在、使用しているのは、 scala.collection.SortedMap
特性、誰の ++
メソッドはから継承されます MapLike
特性。したがって、次のような動作が見られます。
scala> import scala.collection.SortedMap
import scala.collection.SortedMap
scala> val a = SortedMap(1->2, 3->4)
a: scala.collection.SortedMap[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> val b = SortedMap(2->3, 4->5)
b: scala.collection.SortedMap[Int,Int] = Map(2 -> 3, 4 -> 5)
scala> a ++ b
res0: scala.collection.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
scala> b ++ a
res1: scala.collection.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
返される結果の型 ++
です Map[Int, Int]
, 、これが意味をなす唯一のタイプであるため、 ++
の方法 MapLike
返すオブジェクト。のようだ ++
のソートされたプロパティを保持します SortedMap
, 、おそらくそれは次の理由だと思います ++
は抽象メソッドを使用して連結を行い、それらの抽象メソッドはマップの順序を維持するように定義されています。
2 つのソートされたマップを結合するには、次を使用することをお勧めします。 scala.collection.immutable.SortedMap
.
scala> import scala.collection.immutable.SortedMap
import scala.collection.immutable.SortedMap
scala> val a = SortedMap(1->2, 3->4)
a: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> val b = SortedMap(2->3, 4->5)
b: scala.collection.immutable.SortedMap[Int,Int] = Map(2 -> 3, 4 -> 5)
scala> a ++ b
res2: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
scala> b ++ a
res3: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
この実装では、 SortedMap
特性が宣言します ++
を返すメソッド SortedMap
.
ここで、型の境界に関する質問に対するいくつかの答えを示します。
Ordered[T]
クラス内で混合された場合、そのクラスが次を使用して比較できることを指定する特性です。<
,>
,=
,>=
,<=
. 。抽象メソッドを定義するだけですcompare(that: T)
返すもの-1
のためにthis < that
,1
のためにthis > that
そして0
のためにthis == that
. 。次に、他のすべてのメソッドは、次の結果に基づいてトレイトに実装されます。compare
.T <% U
Scala でバインドされたビューを表します。つまりそのタイプですT
~のサブタイプのいずれかですU
または、暗黙的に次のように変換できます。U
スコープ内の暗黙的な変換によって。次のようにするとコードは機能します<%
しかし、そうではありません<:
としてX
のサブタイプではありませんOrdered[X]
ただし、暗黙的に次のように変換できますOrdered[X]
を使用してOrderedX
暗黙的な変換。
編集: いただいたコメントに関して。を使用している場合は、 scala.collection.immutable.SortedMap
, 、不変として、実装ではなくインターフェイスに対してまだプログラミングしています。 SortedMap
として定義されます trait
. 。より特殊な特性として見ることができます。 scala.collection.SortedMap
, 、追加の操作 ( ++
を返す SortedMap
) そして不変であるという性質。これは、不変性を好むという Scala の哲学に沿ったものです。したがって、不変を使用しても問題はないと思います。 SortedMap
. 。この場合、結果が以下になるという事実を保証できます。 絶対に コレクションは不変であるため、これを変更することはできません。
しかし、私はまだ不思議に思っています scala.collection.SortedMap
は提供しません ++
メソッドウィッチは a を返します SortedMap
結果として。私が行った限定的なテストはすべて、2 つの要素を連結した結果であることを示唆しているようです。 scala.collection.SortedMap
s は実際に、sorted プロパティを保持するマップを生成します。
他のヒント
あなたはScalaの初心者としてクラックするのは難しいナットを選びました! : - )
[OK]を、簡単なツアーは、完全に今それを理解することを期待しないでください。まず、問題は方法の++
で起こることに注意してください。その定義の検索、我々はMapLike
またはIterator
のいずれかを受けて、形質Traversable
でそれを見つけます。 y
がSortedMap
あるため、それが使用されているTraversable
バージョンである。
渡されるCanBuildFrom
があること豊富型シグネチャに注意。これは、暗黙のうちに渡されているので、あなたは、通常はそれを心配する必要はありません。しかし、あなたがこの時間に何が起こっているか理解する。
あなたはそれが++
の定義で、またはフィルタリングによって表示され、その上にクリックするかCanBuildFromを見つけることができます。コメントにランドールで述べたように、scaladocページの左上にマークされていない空白のフィールドがあります。あなたはそこをクリックして入力する必要があり、それはそれはあなたが入力したである何のために試合を返します。
だから、ScalaDocに形質CanBuildFrom
を検索して選択します。これは、サブクラスの数が多い、コレクションの特定のタイプを構築するための責任が各1を持っています。検索し、サブクラスSortedMapCanBuildFrom
をクリックしてください。これは、あなたがSortedMap
からTraversable
を生成するために必要なオブジェクトのクラスです。それは暗黙Ordering
パラメータを受信インスタンスコンストラクタ(クラスのコンストラクタ)に注意してください。今、私たちは近づいている。
この時間は、Ordering
を検索するためのフィルタフィルタを使用しています。そのコンパニオンオブジェクトは、(小さい「O」に名前をクリック)コンパニオンオブジェクトはそのクラスのインスタンスまたは変換を生成する暗黙のために検査されるように、Ordering
sを生成することを暗黙をホストします。それはLowPriorityOrderingImplicits
が拡張するオブジェクト形質Ordering
、内部で定義され、唯一の問題がなかった場合は、必要なordered[A <: Ordered[A]]
が生成されます...またはそれを生成する方法のOrdering
を、表示されますそれを見ています。
一つは、私がこれにもっと注意深く見て前に持っていたのと同様に、十分だろうX
へOrdered[X]
からの暗黙的な変換を想定するかもしれません。すなわち、ただし、オブジェクトの変換であり、そしてordered
は Ordered[X]
のサブタイプであるの入力を受信することを期待します。一つは、X
、型Ordered[X]
のオブジェクトにそれ自体を型X
のオブジェクトを変換することができるが、Ordered[X]
のサブタイプではないので、ordered
にパラメータとして渡すことができません。
一方で、あなたの代わりにval
のOrdering[X]
の、暗黙のdef
のOrdered[X]
を作成したり、問題を回避するでしょう。具体的に:
object ViewBoundExample {
class X
def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = {
a ++ b
}
implicit val orderingX = new Ordering[X] { def compare(x: X, y: X) = 0 }
}
私はOrdered
はパープレキシティのいずれかでなければなりません/ほとんどの人々の最初の反応はOrdering
すると思う:なぜ同じことのためのクラスがありますか?後者はjava.lang.Comparable
を拡張前者は、java.util.Comparator
を拡張します。残念ながら、compare
かなり和の型シグネチャの主な相違点:
def compare(that: A): Int // Ordered
def compare(x: T, y: T): Int // Ordering
Ordered[A]
の使用は、1つの A
の定義を変更し、又はOrdered[A]
にA
を変換することができる方法に沿って通過することができるようにするために必要となるA
を拡張するOrdered[A]
のいずれかのために必要です。 Scalaは簡単に後者を行うための完全に可能であるが、その後は、のHAVE の比較する前に、各インスタンスを変換します。
一方、Ordering[A]
の使用は、上記示されたように、単一のオブジェクトの作成を必要とします。あなたはそれを使用すると、あなただけのA
に型compare
の2つのオブジェクトを渡す - 。何のオブジェクトがプロセスで作成されていない取得
だから、持っていたことにいくつかのパフォーマンスの向上がありますが、Ordering
オーバーOrdered
のためのScalaの好みのためにはるかに重要な理由があります。 Ordering
へのコンパニオンオブジェクトで再度確認してください。あなたはそこに定義されたScalaのクラスの多くのためのいくつかの暗黙があることに注意しましょう。あなたは、私はクラスT
ための暗黙のはT
のコンパニオンオブジェクト内の検索されます、そしてそれが起こっているまさにだと先に述べた思い出すことがあります。
このがの同様Ordered
のために行うことができます。しかし、これはOrdering
とOrdered
の両方をサポートしているすべてのメソッドが失敗することを意味し、スティッキングポイントです! Ordering
ためOrdered
のための1つ、1を:Scalaはそれを動作させるために、暗黙のためになりますし、2つを見つけるだろうからです。 Scalaは、エラーメッセージが表示されて断念し、それはあなたが望んでいたであるかを決定することができません。だから、選択がなされなければならなかった、とOrdering
は、より多くのそれのために起こっていた。
duhが、私は署名に代えordered[A <% Ordered[A]]
の、ordered[A <: Ordered[A]]
として定義されていない理由を説明するのを忘れました。私はそうすることが、私は前に述べた二重の暗黙の故障の原因となるだろうが、私は実際にこのようなものをやったし、この特定の方法には問題があるかどうか、二重の暗黙的な問題を抱えていた男を頼むよ疑います。