首页 > 解决方案 > 如何使用 EitherT 在 for 理解中映射选项

问题描述

嗨,我正在尝试执行一个理解,例如

(for {
  player <- playerRepository.findById(playerId) // findById returns EitherT[Future, String, Player]
  teamOpt <- teamRepository.findByPlayer(playerId) // findByPlayer returns EitherT[Future, String, Option[Team]]
  playedMatches <- teamOpt.map(team => playedMatchesRepository.findByTeamId(team.id)) // findByTeamId returns EitherT[Future, String, Seq[PlayedMatches]]
} yield (
  player,
  teamOpt,
  playedMatches
)).fold(
  error => {
    logger.error(s"all error: $error")
    Left(error)
  },
  tuple => {
    logger.debug(s"get success -> $tuple")
    Right(playerDetailResponse(tuple._1, tuple._2, tuple._3))
  }
)

我无法获得正确的结构

playedMatches <- teamOpt.map(team => playedMatchesRepository.findByTeamId(team.id))

编译项目时出现以下错误

[error] /Users/agusgambina/code/soccer/app/services/impl/PlayerServiceImpl.scala:28:17: type mismatch;
[error]  found   : Option[(models.Player, Option[models.Team], cats.data.EitherT[scala.concurrent.Future,String,Seq[models.PlayedMatches]])]
[error]  required: cats.data.EitherT[scala.concurrent.Future,?,?]
[error]       playedMatches <- teamOpt.map(team => playedMatchesRepository.findByTeamId(team.id))
[error]                 ^
[error] one error found

我试图包装

标签: scalascala-cats

解决方案


playedMatches <- teamOpt.map(team => playedMatchesRepository.findByTeamId(team.id)) // findByTeamId returns EitherT[Future, String, Seq[PlayedMatches]]

在这里,您将获得一个 Option[EitherT[Future, String, Seq[PlayedMatches]]] ,它与您用作 Monad 以进行 for 理解的 EitherT[Future, String, ???] 不组成。

您拥有的一个选择是在 teamOpt 上实际使用折叠。

teamOpt.fold(EitherT(Future.successful(Left("Team not Found"): Either[String, Team]))){ team => playedMatchesRepository.findByTeamId(team.id) }

这样,如果为空,则使用错误情况打开选项,如果非空,则使用成功情况。(创建一个以 teamOPt 作为参数的函数,理解起来会更好)

希望能帮助到你

更新 如果是空的情况下成功,并且很高兴返回一个空序列:

teamOpt.fold(
  EitherT(Future.successful(Right(Seq()): Either[String, Seq[PlayedMatches]))
){ team =>
  playedMatchesRepository.findByTeamId(team.id) 
}

推荐阅读