2017-01-24 23 views
1

ネストされたコレクション内のオプションを持ったとき、私は、次の奇妙な問題が発生しました:奇妙な型消去

val works: Array[Option[Int]] = Array(1) 
    .map { t => Some(t)} 

val fails: Array[Array[Option[Int]]] = Array(Array(1)) 
    .map { ts => ts.map { Some(_)} } 
// error: type mismatch; found : Array[Array[Some[Int]]] required: Array[Array[Option[Int]]] 

val worksButUgly: Array[Array[Option[Int]]] = Array(Array(1)) 
    .map { ts => ts.map { case t => (Some(t).asInstanceOf[Option[Int]])}} 

私はそれが道に沿っていくつかの型消去に問題がある可能性があり想像するが、それは期待されていますScalaの動作?誰が正確に何が起こるか知っていますか?

答えて

5

Scalaの配列は不変です。これは、配列が例えば以下のようないくつかの問題を防止する。あなたが何かの配列を作ることができるJavaを、それが何かのスーパークラスの配列であると宣言してから別のサブクラスを入れてください。例えば、リンゴの配列は果物の配列であり、次にバナナを入れます。これに関する最悪の部分は、コンパイル時ではなく、実行時に失敗することです。

このため、Scalaは配列が不変でなければならないと判断しました。つまり、Array[Apple]Array[Fruit]のサブクラスではありません。 (配列とは異なり、不変集合は後でバナナを入れることができないため、不変のコレクションはほとんどの場合共変です(例:List

そうです。 SomeOptionのサブクラスですが、Array[Some]Array[Option]のサブクラスではありません。これらは動作します:

val foo1: Array[Array[Option[Int]]] = Array(Array(1)) 
    .map { ts => ts.map { Option(_)} } 

val foo2: Array[List[Option[Int]]] = Array(List(1)) 
    .map { ts => ts.map { Some(_)} } 
0

利用Some(t): Option[Int]の代わりSome(t).asInstanceOf[Option[Int]]。より短くて安全です。タイプが一致しないとコンパイルに失敗します。