在理解式中,所有单子必须是同一类型。这意味着你不能混合RightProjection
and Option
,因为输出必须是Either
。这是因为 for 理解被转换为嵌套的 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
,这是定义flatMap[AA >: A, Y](f: (B) ⇒ Either[AA, Y]): Either[AA, Y]
,我们看到,结果必须是Either
, but flatMap
of Option
有签名flatMap[B](f: (A) ⇒ Option[B]): Option[B]
。它返回一个Option
并且没有明智的方法来翻译Option
to an Either
.
edit:以下示例并不适用于Either
,请参阅 huynhjl 的链接了解更多信息
但是,除了在 for-compression 中从 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
这节省了我们不必要的分配,也使代码更具可读性。