Reputation: 7063
I'm trying to mix Try
s with Future
s in a for
loop in Scala, without explicitly converting the Try
s to Future
s with Future.fromTry
. It looks like that it works automatically in some cases, but not in others.
The following snippet fails with
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util._
for {
a <- Try(5)
b <- Future(10)
} yield { a + b }
type mismatch;
found : scala.concurrent.Future[Int]
required: scala.util.Try[?]
b <- Future { 10 }
^
Compilation Failed
On the other hand if I remove the keyword yield
, it works:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util._
for {
a <- Try(5)
b <- Future(10)
} { println(a + b) }
It also works when I rewrite the for
loop into a nested foreach
or map
:
@ Try(5) foreach { a => Future(10) foreach { b => println(a + b) } }
15
@ Try(5) map { a => Future(10) map { b => a + b } }
res5: Try[Future[Int]] = Success(Future(Success(15)))
Could someone explain me why is this happening? Is this a bug? Or am I missing something?
ps. it's the same behaviour in Scala 2.11 and 2.12.
Upvotes: 2
Views: 298
Reputation: 22181
foreach
returns a Unit
type; therefore a "common" type.
Without yield
keyword, the compiler interprets your for-comprehension as:
Try(5).foreach(a => Future(10).foreach(b => println(a + b)))
You can deal with Future
and Try
(two distinct monads) as long as you are chaining them around foreach
.
If you add yield
keyword, the compiler will interpret your for-comprehension with flatMap
/map
; as following:
Try(5).flatMap(a => Future(10).map(b => a + b))
The Try#flatMap
expects a function having a Try
as return type, but it gets a Future
, making the whole not compiling.
TL;DR: foreach
does not expect matching of function types during chaining since it returns Unit in all cases; that's why it compiles.
Note that the following:
Try(5) map { a => Future(10) map { b => a + b } }
works since map
does not need to flatten types; so wrapping compiles with distinct "effects".
Flattening distinct types make the compiler fails; as flatMap
attempts to do.
Upvotes: 3