Drafting futures with understanding
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 get Vector
of Categories
wrapped in Future
because it's like ReactiveMongo. As for
I understand it, I am using Vector
to get a list of ids from a database. Finally, I use a call filter
to store only those categories whose ids can be found in this ids list.
Everything seems pretty simple. The problem is Play is giving me the following compilation error on the last line of understanding for
:
pattern type is incompatible with expected type;
found : Vector[com.myapp.Category]
required: com.myapp.Category
I'm not sure why the required type is a single instance Category
.
I could use some idea of ββwhat I am doing wrong and / or if there is an easier or more idiomatic way of accomplishing this.
source to share
It looks like you are trying to compose Futures
with Vector
. For understanding, scala should have all the same higher types as in your case Future
. When you open up "sugar" for understanding, he just calls flatMap
everyone.
for {
categories <- categoriesFuture
// I'm not sure what the return type is here, but I'm guessing it 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 de-sugared code:
categoriesFuture.flatMap(categories =>
findCategoryIdsWithoutPerson(categories.map(_.id), personId).
flatMap(categoryIdsWithoutPerson =>
categories.filter(category => categoryIdsWithoutPerson.contains(category.id)).
map(_ => categoryIdsWithoutPerson))
source to share