2013-01-19 14 views
5

私がList(1.0, 2)を要求すると、Scala(2.10)で、List[Double]が予想どおりに取得されます。予期しないスカラマップタイプ

しかし...

私はMap[AnyVal, Char]を得るMap(1.0 -> 'A', 2 -> 'B')をお願いします。私は鍵がタイプDoubleであることを望みます。 Map[Double, Char](1.0 -> 'A', 2 -> 'B)を求めると、 '2'にタイプの不一致が生じます。

これは私が最も混乱しているとわかります!それは矛盾していませんか?

脇に:List[(Double, Char)]((1.0, 'A'), (2, 'B')).toMap私には[Double、Char]のマップがあります。

+0

2.9.2でも再現可能です。 –

答えて

6

あなたはScalaのtype hierarchyに見れば、プリミティブ型は、サブタイプ/スーパータイプ関係にないことがわかります。しかし、数値拡大と呼ばれるメカニズムがあります。たとえば、Intを渡して、Double引数を取るメソッドを呼び出すことができます。 Intは自動的にDoubleに「拡大」されます。

List(1.0, 2)があなたにList[Double]を与える理由です。

しかし、Mapコンストラクタには、Tuple[A, B]引数が必要です。数値の拡大は高次の型には適用されないので、数値型を混在させるとターゲット型の推論が機能しません。

case class Test[A](tup: (A, Char)*) 
Test(1.0 -> 'A', 2 -> 'B') // AnyVal 

また、矢印演算子->はあなたの方法で取得します。

Test[Double](2 -> 'B') // found: (Int, Char) required: (Double, Char) 

これは私が考えて型推論の別の制限です。 a -> bのタプルの記述は、暗黙のメソッドany2ArrowAssocPredefで提供される(a, b)の構文的な砂糖です。

Test[Double]((2, 'B')) 

だから数字の拡大はまだ動作しませんが、少なくとも、あなたはタイプ強制することができます:あなたが直接Tuple2を構築する場合は、この間接せず、それが動作します

Map[Double, Char]((1.0, 'A'), (2, 'B')) 

を数字の拡大作業を示す最後の例:

def map[A, B](keys: A*)(values: B*) = Map((keys zip values): _*) 
map(1.0, 2)('A', 'B') // Map[Double, Char] 
3

リストの場合、型宣言なしでは、すべての要素を調べ、共通型を検索しようとします。あなたのケースでは、IntはDoubleに変換できるので、混合リストをリストに変換します。[Double]あなたのIntを宣伝します。

マップコンストラクタは、一連の2タプルを取ります。

scala> List((1, "one"), (2.0, "two.oh")) 
res0: List[(AnyVal, String)] = List((1,one), (2.0,two.oh)) 

Tuple2 [INT、文字列]は自動的にTuple2 [ダブル、文字列]に昇格することができません。あなただけのタプルのリストを構築している場合は、同じ動作になるだろう。何らかの理由で

scala> val x = List[(Double, String)]((1, "one"), (2.0, "two.oh")).toMap 
x: scala.collection.immutable.Map[Double,String] = Map(1.0 -> one, 2.0 -> two.oh) 

scala> val x: List[(Double, String)] = List((1, "one"), (2.0, "two.oh")) 
x: List[(Double, String)] = List((1.0,one), (2.0,two.oh)) 

または

scala> val x = List[(Double, String)]((1, "one"), (2.0, "two.oh")) 
x: List[(Double, String)] = List((1.0,one), (2.0,two.oh)) 

またはあなたの場合:この場合、あなたは型宣言でビットをコンパイラを手助けする必要がありますマップ上の型宣言を使用しても機能しません。わからない理由:

scala> val x = Map[Double, String](1 -> "one", 2.0 -> "two.oh") 
<console>:7: error: type mismatch; 
found : (Int, String) 
required: (Double, String) 
    val x = Map[Double, String](1 -> "one", 2.0 -> "two.oh")