我为了理解而编写了一个代码,我想知道一些事情:
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)
}
使用不返回A的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
谢谢
发布于 2013-04-21 18:25:05
在for理解中,所有的monad都必须是同一类型的。这意味着您不能混合使用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
,但是Option
的flatMap
有签名flatMap[B](f: (A) ⇒ Option[B]): Option[B]
。它返回一个Option
,并且没有一种合理的方法将Option
转换为Either
。
编辑:以下示例不能使Either
工作安静,有关更多信息,请参阅link by 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
这为我们节省了不必要的分配,也使代码更具可读性。
https://stackoverflow.com/questions/16130039
复制相似问题