Can someone please elaborate what it means when the types have to align with scala for comprehensions?
for {
..
..
}
If the calls all return Futures then it will be fine? Just trying to understand when it works and when it doesn't work.
For-comprehension desugars to map/flatMap calls so consider their signatures. For example, consider Option#flatMap
def flatMap[B](f: (A) => Option[B]): Option[B]
We see Option
s continue to be involved. Now observe since
for {
a <- Some(41)
b <- Some(1)
} yield a + b
becomes
Some(41).flatMap(a => Some(1).map(b => a + b))
that means if you tried to mix monadic types inside for-comprehension such as
for {
a <- Some(41)
b <- Try(1)
} yield a + b
then it would desugar to
Some(41).flatMap(a => Try(1).map(b => a + b))
|
types do not align
but we already seen that Option#flatMap
expects A => Option[B]
not A => Try[B]
.
One place where it seems as if you can break that rule is when mixing Option with List
scala> for {
| a <- List(41)
| b <- Some(1)
| } yield (a + b)
val res0: List[Int] = List(42)
but this works because List#flatMap
takes a function from A
to IterableOnce
and Option
has been made IterableOnce
in Scala 2.13
def flatMap[B](f: A => IterableOnce[B])
Note the other way around will not work though:
scala> for {
| a <- Some(41)
| b <- List(1)
| } yield a + b
b <- List(1)
^
On line 3: error: type mismatch;
found : List[Int]
required: Option[?]
In general given an effectful type F[A]
then inside for-comprehension F
cannot vary unless we are using a subtype, on the other hand A
can indeed vary.