Skip to content

Unexpected type error in for comprehension using List and Option #7941

@scabug

Description

@scabug

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions