-
Notifications
You must be signed in to change notification settings - Fork 21
Closed
Labels
Description
When combining List and Option in a for comprehension a confusing type error is reported.
I was writing code similar to this example:
object Test {
val list = List(1,2,3)
val map = Map(1 -> List('a', 'b', 'c'), 3 -> List())
for {
// Pick a number from the list.
number <- list
// Lookup a list of chars in a map using the number as key.
// Get returns an Option so use a generator to discard Nones.
chars <- map.get(number)
// Iterate over the chars.
char <- chars
} yield char
}Compiling it, results in this error message:
$ scalac -version
Scala compiler version 2.10.3 -- Copyright 2002-2013, LAMP/EPFL
$ scalac test.scala
test.scala:13: error: type mismatch;
found : List[Char]
required: Option[?]
char <- chars
^
one error found
$ The example above can be reduced to this code:
object Test {
for {
xs <- Some(List(1,2,3))
x <- xs
} yield x
}which can be mechanically rewritten to
object Test {
Some(List(1,2,3)) flatMap (xs => xs) map (x => x)
}Compiling this code...
$ scalac test.scala
test.scala:2: error: type mismatch;
found : List[Int]
required: Option[?]
Some(List(1,2,3)) flatMap (xs => xs) map (x => x)
^
one error found
$ ...reveals the cause of the problem: Unlike other collections, {{Option}}'s {{flatMap}} cannot produce anything but an {{Option}}.
Converting the Option to a List using toList is a workaround but it requires insight into the collection implementation to discover this workaround.