質問

(私は 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.SortedMaps は実際に、sorted プロパティを保持するマップを生成します。

他のヒント

あなたはScalaの初心者としてクラックするのは難しいナットを選びました! : - )

[OK]を、簡単なツアーは、完全に今それを理解することを期待しないでください。まず、問題は方法の++で起こることに注意してください。その定義の検索、我々はMapLikeまたはIteratorのいずれかを受けて、形質Traversableでそれを見つけます。 ySortedMapあるため、それが使用されているTraversableバージョンである。

渡されるCanBuildFromがあること豊富型シグネチャに注意。これは、暗黙のうちに渡されているので、あなたは、通常はそれを心配する必要はありません。しかし、あなたがこの時間に何が起こっているか理解する。

あなたはそれが++の定義で、またはフィルタリングによって表示され、その上にクリックするかCanBuildFromを見つけることができます。コメントにランドールで述べたように、scaladocページの左上にマークされていない空白のフィールドがあります。あなたはそこをクリックして入力する必要があり、それはそれはあなたが入力したである何のために試合を返します。

だから、ScalaDocに形質CanBuildFromを検索して選択します。これは、サブクラスの数が多い、コレクションの特定のタイプを構築するための責任が各1を持っています。検索し、サブクラスSortedMapCanBuildFromをクリックしてください。これは、あなたがSortedMapからTraversableを生成するために必要なオブジェクトのクラスです。それは暗黙Orderingパラメータを受信インスタンスコンストラクタ(クラスのコンストラクタ)に注意してください。今、私たちは近づいている。

この時間は、Orderingを検索するためのフィルタフィルタを使用しています。そのコンパニオンオブジェクトは、(小さい「O」に名前をクリック)コンパニオンオブジェクトはそのクラスのインスタンスまたは変換を生成する暗黙のために検査されるように、Orderingsを生成することを暗黙をホストします。それはLowPriorityOrderingImplicitsが拡張するオブジェクト形質Ordering、内部で定義され、唯一の問題がなかった場合は、必要なordered[A <: Ordered[A]]が生成されます...またはそれを生成する方法のOrderingを、表示されますそれを見ています。

一つは、私がこれにもっと注意深く見て前に持っていたのと同様に、十分だろうXOrdered[X]からの暗黙的な変換を想定するかもしれません。すなわち、ただし、オブジェクトの変換であり、そしてordered Ordered[X]のサブタイプであるの入力を受信することを期待します。一つは、X、型Ordered[X]のオブジェクトにそれ自体を型Xのオブジェクトを変換することができるが、Ordered[X]のサブタイプではないので、orderedにパラメータとして渡すことができません。

一方で、あなたの代わりにvalOrdering[X]の、暗黙のdefOrdered[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のために行うことができます。しかし、これはOrderingOrderedの両方をサポートしているすべてのメソッドが失敗することを意味し、スティッキングポイントです! OrderingためOrderedのための1つ、1を:Scalaはそれを動作させるために、暗黙のためになりますし、2つを見つけるだろうからです。 Scalaは、エラーメッセージが表示されて断念し、それはあなたが望んでいたであるかを決定することができません。だから、選択がなされなければならなかった、とOrderingは、より多くのそれのために起こっていた。

duhが、私は署名に代えordered[A <% Ordered[A]]の、ordered[A <: Ordered[A]]として定義されていない理由を説明するのを忘れました。私はそうすることが、私は前に述べた二重の暗黙の故障の原因となるだろうが、私は実際にこのようなものをやったし、この特定の方法には問題があるかどうか、二重の暗黙的な問題を抱えていた男を頼むよ疑います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top