首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Options和for comprehensions

Options和for comprehensions
EN

Stack Overflow用户
提问于 2013-04-21 18:07:34
回答 1查看 2.1K关注 0票数 7

我为了理解而编写了一个代码,我想知道一些事情:

代码语言:javascript
运行
复制
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,但它不起作用,有人能解释一下为什么吗?

代码语言:javascript
运行
复制
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

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-21 18:25:05

在for理解中,所有的monad都必须是同一类型的。这意味着您不能混合使用RightProjectionOption,因为输出必须是Either。这是因为for-comprehension被转换为嵌套的flatMap/map构造。您的示例将如下所示:

代码语言:javascript
运行
复制
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,但是OptionflatMap有签名flatMap[B](f: (A) ⇒ Option[B]): Option[B]。它返回一个Option,并且没有一种合理的方法将Option转换为Either

编辑:以下示例不能使Either工作安静,有关更多信息,请参阅link by huynhjl

但是,除了可以从for-comprehension中的monad中提取值之外,还可以创建变量,因此您的示例可以重写为:

代码语言:javascript
运行
复制
def updateUserStats(user: User): Either[Error,User] = for {
  stampleCount <- stampleRepository.getStampleCount(user).right
  userUpdated = copyUserWithStats(user,stampleCount)
  userSaved <- userService.update(userUpdated).right
} yield userSaved

这为我们节省了不必要的分配,也使代码更具可读性。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16130039

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档