我正在为了理解而编码,并想知道:
def updateUserStats(user: User): Either[Error,User] = for {
stampleCount <- stampleRepository.getStampleCount(user).right
userUpdated <- Right(copyUserWithStats(user,stampleCount)).right // ?????????
userSaved <- userService.update(userUpdated).right
} yield userSaved
def copyUserWithStats(user: User, stamples: Long): User = {
val newStats = user.userStats.copy(stamples = stamples)
user.copy(userStats = newStats)
}
似乎使用不返回Either的copyUserWithStats不能直接用于for comprehension,因为它没有map / flatMap方法。
所以我想知道,在这种情况下,它是使用Right(copyUserWithStats(user,stampleCount)).right
它似乎至少起作用了......
顺便说一句,我也尝试使用Option,但它没有用,有人可以解释原因吗?
def updateUserStats(user: User): Either[Error,User] = for {
stampleCount <- stampleRepository.getStampleCount(user).right
userUpdated <- Some(copyUserWithStats(user,stampleCount))
userSaved <- userService.update(userUpdated).right
} yield userSaved
由于
答案 0 :(得分:10)
在理解中,所有单子都必须是同一种。这意味着您无法混合RightProjection
和Option
,因为输出必须是Either
。这是因为for-comprehension被转换为嵌套的flatMap / map构造。你的例子看起来像这样:
def updateUserStats(user: User): Either[Error,User] =
stampleRepository.getStampleCount(user).right.flatMap { stampleCount =>
Some(copyUserWithStats(user,stampleCount)).flatMap { userUpdated =>
userService.update(userUpdated).right.map { userSaved =>
userSaved
}
}
}
如果我们现在查看RightProjection.flatMap
的签名,那就是def
我们看到flatMap[AA >: A, Y](f: (B) ⇒ Either[AA, Y]): Either[AA, Y]
,结果必须是Either
,但flatMap
Option
的签名为flatMap[B](f: (A) ⇒ Option[B]): Option[B]
。它会返回Option
,并且没有合理的方式将Option
翻译为Either
。
修改:以下示例不会为Either
安静工作,请参阅huynhjl链接以获取更多信息
但是,除了在for-comprehension中从monad中提取值之外,还可以创建变量,因此您的示例可以重写为:
def updateUserStats(user: User): Either[Error,User] = for {
stampleCount <- stampleRepository.getStampleCount(user).right
userUpdated = copyUserWithStats(user,stampleCount)
userSaved <- userService.update(userUpdated).right
} yield userSaved
为我们节省了不必要的分配,也使代码更具可读性。