Reputation: 1407
I want to get the product of a List[Option[Int]]
, and flatten it to Option[Int]
:
List(Some(2), Some(3), Some(5)).foldLeft(Some(1)) { (x, y) =>
// err
x.map(ix => y.map(iy => ix * iy)).flatten
// // workaround
// x.map(ix => y.map(iy => ix * iy)).flatten match {
// case Some(acc) => Some(acc)
// case _ => Some(0)
// }
}
the err in detail:
polymorphic expression cannot be instantiated to expected type;
[error] found : [B]Option[B]
[error] required: Some[Int]
[error] x.map(ix => y.map(iy => ix * iy)).flatten
[error]
flatten
in foldLeft
didn't return Some[Int]
? What's going on?
Upvotes: 0
Views: 197
Reputation: 4999
x.map(ix => y.map(iy => ix * iy)).flatten
returns an Option[Int]
, based on the value of the x
and y
, i.e. if either x
or y
is None
the value is None
, otherwise it is Some[Int]
.
In your fold statement, your seed value is Some(1)
whose type is Some[Int].
Compiler expects the same type from the result of the fold statement. But the result value of the expression of the fold statement is Option[Int]
. Hence, the error, the required type is Some[Int]
as of the seed value, but compiler found Option[Int]
from the fold expression.
Any of the other answer works. The closet to your expression will be simply change your seed value to Option(1)
from Some(1)
, so that the type of seed value and type from the fold statement matches, like
List(Some(2), Some(3), Some(5)).foldLeft(Option(1)) { (x, y) => ....
Upvotes: 2
Reputation: 1580
This works and is simpler:
List(Some(2), Some(3), Some(5)).flatten.foldLeft(1) { (x, y) => x * y}
Flattten removes Nones and gives you List[Int].
Upvotes: 0
Reputation: 1086
If your list is actually a List[Option[Int]]
then for a working example you need to declare them as such. It would be great if someone could chime in on exactly why since I'm not sure.
val xs = List(Option(2), Option(3), Option(5))
xs.reduceRight((x, b) => x.flatMap(y => b.map(z => y * z)))
// res0: Option[Int] = Some(30)
Note however if any element in the list of Options is None
then the evaluation will "short circuit" and return a None
. If you don't want this then I believe you will need to look at some solutions from scalaz
such as applicative functors, there's some discussion this here Summing a List of Options with Applicative Functors
Upvotes: 1