2017-03-07 15 views
0

Scala Set/Mapは、有線型の推論につながる可能性があります。例えばScalaでのマップの型推論

、REPL

$ val m2 = Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty) 
> scala.collection.immutable.Map[String,scala.collection.immutable.Map[_ <: String, Int]] = Map(foo -> Map(bar -> 6), baz -> Map()) 

に私はimmutable.MapタイプにつながることができるいくつかのCanBuildFromと "デフォルト" について知っています。

なぜ内部が...Map[String, Int]ではなく...Map[_ <: String, Int]であるのですか?

観察:予想通り以下に定義

m1

が推測されます。明示的な型帰属することにより

$ val m1 = Map("foo" -> Map("bar" -> 5)) 
> scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Int]] = Map(foo -> Map(bar -> 5)) 

、両方が(私はこれが原因CanBuildFromにあると思います)、「正しく」に変換することができます。

val _m1: Map[String, Map[String, Int]] = Map("foo" -> Map("bar" -> 5)) 
val _m2: Map[String, Map[String, Int]] = Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty) 

私は例えば、私は、いくつかの機能のライブラリを使用するときため、この気に、 catsの場合は、両方のオペランドが同じ型であることを確認しなければなりません。型ascensionを使用するときは、を知りたいと思います。例えば、ここでは仕事で何CanBuildFrom秒、Mapキーの唯一の不変性は

import cats.Semigroup 
import cats.implicits._ 
m1 ++ m2 // works 
m1 |+| m2 // error 
// found : scala.collection.immutable.Map[String,scala.collection.immutable.Map[_ <: String, Int]] 
// required: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Int]] 

答えて

2

はありません。

あなたが書くとき:

Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty) 

を--the 少なくとも上限をコンパイラは、このタイプを推測しようとし、そうすることで、それはMap("bar" -> 6)の一般的なタイプを把握する必要があり、Map.empty 。あなたは型パラメータを指定しない場合

Map.emptyMap[Nothing, Nothing]なので、コンパイラはMap[String, Int]Map[Nothing, Nothing]の上限少なくとも計算し、それが実存タイプMap[_ <: String, Int]を思い付きます。これは、Mapの不変式であるためです。あなたはコンパイラがMap.emptyの型パラメータを推測するために使用するヒントを追加しているので、あなたが型注釈を追加したときにそれが動作

Map[Nothing, Int]Map[String, Int]ではありません)。ヒントがなければ、喜んでMap[Nothing, Nothing]を使用します。これは型推論のわずかな欠陥ですか?多分。私はいつもCollectionType.emptyというタイプのパラメータを安全なものにすることを好みます。

val m2 = Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty[String, Int]) 
+0

私はMap [String、Int]とmap [Nothing、Nothing]のlupが、実在の型 'Map [_ <:String、Int]'である理由を知っていますか? –

+1

他のマップを 'Map [Int、Int]'や何か他のものにすると、コンパイラがLUBを実体型としてどのように構築するのかが分かります。 'SomeOtherType'は、コンパイラが何か役に立つものに詰め込もうとしている互換性のない型です。'Nothing with String'は' String'だけで、 'String with Nothing'を' String'に置き換えます。 –

+0

しかし、それは異なっています、少なくとも方向は逆ですか? –