The following works fine:
def show(id: Int) = myAction asyc {
for {
users <- userService.getAll()
locations <- locationService.getByUsers(users)
} yield {
Ok("hi")
}
}
But if I do this:
for {
users <- userService.getAll()
locations <- locationService.getByUsers(users)
} yield {
for {
f1 <- ...
f2 <- ....
} yield {
Ok("hi")
}
}
I get a type mismatch error:
found : scala.concurrent.Future[play.api.mvc.Result]
[error] required: play.api.mvc.Result
[error] f1 <- ....
Hoping someone can explain this for me.
Adding type annotations might help make clearer what's going on:
val result: Future[Future[Result]] = for {
users <- userService.getAll()
locations <- locationService.getByUsers(users)
} yield {
val innerResult: Future[Result] = for {
f1 <- ...
f2 <- ....
} yield {
Ok("hi")
}
innerResult
}
By yielding a Future[Result]
(innerResult
), you're causing the outermost for
to be of type Future[Future[Result]]
.
We know that result
is going to have to be of type Future[???] (determined by the type of the first generator, userService.getAll()
). It winds up being a Future[Future[Result]]
because you yield a Future[Result]
.
The solution is to yield a Result
intead:
def foo(users: Seq[User], locations: Seq[Location]): Future[Result] = {
for {
f1 <- ...
f2 <- ....
} yield {
Ok("hi")
}
}
for {
users <- userService.getAll()
locations <- locationService.getByUsers(users)
result <- foo(users, locations)
} yield result