2017-01-24 1 views
1

j'ai rencontré la question bizarre suivante lorsque l'option ayant dans les collections imbriquées:effacement de type étrange pour l'option dans la collection imbriquée

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]])}} 

J'imagine que ce peut être un problème avec un certain effacement de type le long du chemin, mais est-il l'attendu comportement à Scala? Est-ce que quelqu'un sait ce qui se passe exactement?

Répondre

5

Les tableaux de Scala sont invariants. Cela évite certains problèmes que les tableaux ont, par exemple, Java, où vous pouvez créer un tableau de quelque chose, le proclamer comme un tableau de super-classe de quelque chose, puis mettre une autre sous-classe. Par exemple, dire qu'un tableau de pommes est un tableau de fruits et ensuite mettre des bananes. Le pire à ce sujet est qu'il échoue à l'exécution, pas au moment de la compilation. Pour cette raison, Scala a décidé que les tableaux devraient être invariants. Cela signifie que Array[Apple] n'est pas une sous-classe de Array[Fruit]. (Notez que contrairement aux tableaux, les collections immuables sont le plus souvent covariantes, par exemple List, car l'immutabilité nous empêche d'y insérer des bananes plus tard)

Alors oui. Some est une sous-classe de Option, mais Array[Some] n'est pas une sous-classe de Array[Option]. Ceux-ci travailleront:

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

Utilisation Some(t): Option[Int] au lieu de Some(t).asInstanceOf[Option[Int]]. Il est à la fois plus court et plus sûr: il ne pourra pas être compilé si les types ne correspondent pas.