The problem is that you want to flatMap a List[Option[T]] to a List[T] :
val l = List(Some("Hello"), None, Some("World"))
to get:
List(Hello, World)
but there is no nice solution:
l flatMap( o => o)
l flatMap identity[Option[String]]
l flatMap ( x => Option.option2Iterable(identity(x)))
for(x <- l; y <- x) yield y
The obvious solution using the identity function does not work, due to a needed type conversion from Option[T] to Iterable[T]:
l flatMap identity
<console>:6: error: type mismatch;
found : A
required: Iterable[?]
l flatMap identity
Is there a way around this problem?
Part of the question is why does the type inferencer work differently if implicit type conversions are needed?
(This question came up when this question about the identity function was discussed.)
There is no problem with the implicit. If it were a list of list, you wouldn’t be able to pass
identitytomaporflatMapeither. Let’s discussmapinstead offlatMap, because it is simpler, so that I can better explain what I think is happening.The type of
identityis(A) => A. The type ofmapif(A) => B, whereAis known, because it is the type parameter of the object (ie, in aList[String], it isString). Neitheridentity‘sAnormap‘sBis known.Now, if we used the left side of
map‘s type to infer the left side ofidentity, then we could use the right side ofidentityto infer the right side ofmap. See a cycle?map‘s type toidentity‘s type tomap‘s type again. I’m pretty sure the type inferencer avoids cycles, otherwise it could be stuck in an infinite loop.In fact, one can look at page 355 of Odersky et al’s Programming in Scala the details of the type inferencer. In a method application
m(arg), it does the following steps:m(map, in our case) has a known type (no, we don’t knowB).arg(identityin our case) has a known type (no, we don’t knowA).So, you have to provide one type. For example:
On Scala 2.8 the type inferencer is a little bit cleverer, and can handle the second command without passing the type explicitly.