Composing Futures with For Comprehension
for-comprehension, future, reactivemongo, scala
Solution
It looks like you're trying to compose `Futures` with `Vector`. For comprehensions in scala have to all be of the same higher type, which in your case is `Future`. When you unroll the 'sugar' of the for comprehension, it's just calling `flatMap` on everything.
for {
categories <- categoriesFuture
// I'm not sure what the return type is here, but I'm guessing it's a future as well
categoryIdsWithoutPerson <- findCategoryIdsWithoutPerson(categories.map(_.id), personId)
// Here we use = to get around need to flatMap
categoriesWithoutPerson = categories.filter(category => categoryIdsWithoutPerson.contains(category.id))
} yield categoryIdsWithoutPerson
Your code de-sugared:
categoriesFuture.flatMap(categories =>
findCategoryIdsWithoutPerson(categories.map(_.id), personId).
flatMap(categoryIdsWithoutPerson =>
categories.filter(category => categoryIdsWithoutPerson.contains(category.id)).
map(_ => categoryIdsWithoutPerson))
Problem
I have a Play Framework application using ReactiveMongo with MongoDB, and I have the following code: ``` def categories(id: String): Future[Vector[Category]] = {...} .... val categoriesFuture = categories(id) for { categories: Vector[Category] <- categoriesFuture categoryIdsWithoutPerson: Vector[BSONObjectID] <- findCategoryIdsWithoutPerson(categories.map(_.id), personId) //Returns Future[Vector[BSONObjectID]] categoriesWithoutPerson: Vector[Category] <- categories.filter(category => categoryIdsWithoutPerson.contains(category.id)) //Play cites the error here } yield categoryIdsWithoutPerson ``` To explain this code, I fetch a `Vector` of `Categories` wrapped in a `Future` because that's how ReactiveMongo rolls. In the `for` comprehension, I use that `Vector` to then fetch a list of ids from the database. Finally, I use a `filter` call to keep only those categories whose ids can be found in that id list. It all seems fairly straightforward. The problem is that Play gives me the following compilation error on the last line of the `for` comprehension: ``` pattern type is incompatible with expected type; found : Vector[com.myapp.Category] required: com.myapp.Category ``` I am not sure why the required type is a single instance of `Category`. I could use some insight into what I am doing wrong and/or if there is a simpler or more idiomatic way of accomplishing this.