我有一个使用ReactiveMongo和MongoDB的Play Framework应用程序,我有以下代码:
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
为了解释此代码,我获取Vector
Categories
Future
包裹在for
中,因为这就是ReactiveMongo的滚动方式。在Vector
理解中,我使用filter
然后从数据库中获取id列表。最后,我使用for
调用来仅保留可在该ID列表中找到ID的类别。
这一切看起来都相当简单。问题是Play在pattern type is incompatible with expected type;
found : Vector[com.myapp.Category]
required: com.myapp.Category
理解的最后一行给出了以下编译错误:
Category
我不确定为什么所需类型是{{1}}的单个实例。
我可以使用一些洞察我做错了什么和/或是否有更简单或更惯用的方法来实现这一点。
答案 0 :(得分:5)
您似乎正在尝试使用Futures
撰写Vector
。对于scala中的理解,必须具有相同的更高类型,在您的情况下为Future
。当您展开for the understanding的'sugar'时,它只是在所有内容上调用flatMap
。
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
你的代码消失了:
categoriesFuture.flatMap(categories =>
findCategoryIdsWithoutPerson(categories.map(_.id), personId).
flatMap(categoryIdsWithoutPerson =>
categories.filter(category => categoryIdsWithoutPerson.contains(category.id)).
map(_ => categoryIdsWithoutPerson))