2010-05-20 3 views
2

Dans l'extrait de code ci-dessous - pourquoi dois-je donner une annotation de type pour Nil?Pourquoi l'inferenceur de type Scala ne peut-il pas résoudre ce problème?

Welcome to Scala version 2.8.0.RC2 (OpenJDK Server VM, Java 1.6.0_18). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> List(Some(1), Some(2), Some(3), None).foldLeft(Nil)((lst, o) => o match { case Some(i) => i::lst; case None => lst })   
<console>:6: error: type mismatch; 
found : List[Int] 
required: object Nil 
    List(Some(1), Some(2), Some(3), None).foldLeft(Nil)((lst, o) => o match { case Some(i) => i::lst; case None => lst }) 
                          ^

scala> List(Some(1), Some(2), Some(3), None).foldLeft(Nil:List[Int])((lst, o) => o match { case Some(i) => i::lst; case None => lst }) 
res1: List[Int] = List(3, 2, 1) 

Répondre

3

Le problème est que Nil est un objet qui se prolonge List. Cela signifie que Nil.type est une sous-classe de List et, par conséquent, le type d'accumulateur foldLeft sera Nil.type.

C'est un endroit où je souhaite que Scala essaye un peu (ou beaucoup, quoi qu'il en soit) de plus difficile d'obtenir un meilleur type inféré.

0

Vous pouvez éviter la peine de le faire comme ça

private def removeNone[A](xs:List[Option[A]]) = { 
    xs.filter(_.isInstanceOf[Some[_]]).map(_ match { 
     case Some(t) => t 
     case _ =>().asInstanceOf[A] //can't happen, needed to avoid warning 
    }) 
} 

Bien que cela puisse ne pas répondre directement à votre question, je l'ai écrit cette fonction il y a deux heures et je pensais que cela ne pouvait pas nuire à partager. Vous pouvez omettre le 2ème cas si cela ne vous dérange pas d'obtenir un avertissement.

Je trouve également la combinaison de carte et de filtre plus facile à lire que le pli. J'essaie d'utiliser le pli seulement si nécessaire.

Questions connexes