选项和理解

Seb*_*ber 5 monads scala 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)
}
Run Code Online (Sandbox Code Playgroud)

似乎使用copyUserWithStats不返回Either不能直接用于for comprehension,因为它没有map/flatMap方法.

所以我想知道,在这种情况下,它是适当的解决方案 Right(copyUserWithStats(user,stampleCount)).right

它似乎至少起作用......

顺便说一句,我也尝试过选择但它没有用,有人可以解释为什么吗?

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
Run Code Online (Sandbox Code Playgroud)

谢谢

dre*_*xin 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
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

如果我们现在看的签名RightProjection.flatMap,这是高清 flatMap[AA >: A, Y](f: (B) ? Either[AA, Y]): Either[AA, Y],我们看到,这个结果必须是一个Either,但flatMapOption有签名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
Run Code Online (Sandbox Code Playgroud)

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