选项和理解

时间:2013-04-21 10:07:34

标签: scala monads either

我正在为了理解而编码,并想知道:

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

由于

1 个答案:

答案 0 :(得分:10)

在理解中,所有单子都必须是同一种。这意味着您无法混合RightProjectionOption,因为输出必须是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

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

相关问题