选择和理解 [英] Either, Options and for comprehensions
问题描述
我正在为理解编写代码,想知道一些事情:
I was coding a for comprehension, and wondered something:
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理解中使用,因为它没有map/flatMap方法.
It seems using copyUserWithStats which does not return an Either can't be used directly in the for comprehension, because it doesn't have the map/flatMap methods.
所以我想知道,在这种情况下,使用Right(copyUserWithStats(user,stampleCount)).right
So I wonder, in this case, it is the appropriate solution to use Right(copyUserWithStats(user,stampleCount)).right
它似乎至少可以工作...
It seems to work at least...
顺便说一句,我也尝试了Option,但是它没有用,有人可以解释为什么吗?
By the way, I also tried with Option but it didn't work, can someone explain why?
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
谢谢
推荐答案
在理解中,所有单子必须是同一类.这意味着您不能混用RightProjection
和Option
,因为输出必须是Either
.这是因为对理解的理解是翻译成嵌套的flatMap/map构造.您的示例如下所示:
In a for-comprehension all monads have to be of the same kind. That means you can not mix RightProjection
and Option
, because the output has to be an Either
. This is because the for-comprehension gets translated to a nested flatMap/map construct. Your example would look like this:
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
.
If we now look at the signature of RightProjection.flatMap
, which is def
flatMap[AA >: A, Y](f: (B) ⇒ Either[AA, Y]): Either[AA, Y]
, we see, that the result has to be an Either
, but flatMap
of Option
has the signature flatMap[B](f: (A) ⇒ Option[B]): Option[B]
. It returns an Option
and there is no sane way to translate an Option
to an Either
.
编辑:以下示例无法使Either
正常工作,请参阅huynhjl的链接以获取更多信息
edit: Following example does not quiet work for Either
, see link by huynhjl for more information
但是,除了可以理解地从monad中提取值之外,您还可以创建变量,因此您的示例可以重写为:
However you can besides extracting values from monads in a for-comprehension also create variables, so your example could be rewritten as:
def updateUserStats(user: User): Either[Error,User] = for {
stampleCount <- stampleRepository.getStampleCount(user).right
userUpdated = copyUserWithStats(user,stampleCount)
userSaved <- userService.update(userUpdated).right
} yield userSaved
这为我们节省了不必要的分配,并使代码更具可读性.
which saves us an unnecessary allocation and also makes the code more readable.
这篇关于选择和理解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!