如何使用 EitherT 映射内部的选项以供理解
How to map an Option inside a for comprehension with EitherT
您好,我正在尝试执行类似
的理解
(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
我试着包起来
playedMatches <- teamOpt.map(team => playedMatchesRepository.findByTeamId(team.id)) // findByTeamId returns EitherT[Future, String, Seq[PlayedMatches]]
在这里,您将获得一个 Option[EitherT[Future, String, Seq[PlayedMatches]]],它不与您用作 Monad 的 EitherT[Future, String, ???] 组合为了理解。
你有一个选择是在 teamOpt 上实际使用弃牌。
teamOpt.fold(EitherT(Future.successful(Left("Team not Found"): Either[String, Team]))){ team => playedMatchesRepository.findByTeamId(team.id) }
通过这种方式,如果 Option 为空则用错误情况解包,如果非空则用成功情况解包。 (创建一个以teamOPt为参数的函数,for-comprehension看起来会好很多)
希望对您有所帮助
更新
如果空 case 成功,并且很高兴返回一个空序列:
teamOpt.fold(
EitherT(Future.successful(Right(Seq()): Either[String, Seq[PlayedMatches]))
){ team =>
playedMatchesRepository.findByTeamId(team.id)
}
您好,我正在尝试执行类似
的理解(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
我试着包起来
playedMatches <- teamOpt.map(team => playedMatchesRepository.findByTeamId(team.id)) // findByTeamId returns EitherT[Future, String, Seq[PlayedMatches]]
在这里,您将获得一个 Option[EitherT[Future, String, Seq[PlayedMatches]]],它不与您用作 Monad 的 EitherT[Future, String, ???] 组合为了理解。
你有一个选择是在 teamOpt 上实际使用弃牌。
teamOpt.fold(EitherT(Future.successful(Left("Team not Found"): Either[String, Team]))){ team => playedMatchesRepository.findByTeamId(team.id) }
通过这种方式,如果 Option 为空则用错误情况解包,如果非空则用成功情况解包。 (创建一个以teamOPt为参数的函数,for-comprehension看起来会好很多)
希望对您有所帮助
更新 如果空 case 成功,并且很高兴返回一个空序列:
teamOpt.fold(
EitherT(Future.successful(Right(Seq()): Either[String, Seq[PlayedMatches]))
){ team =>
playedMatchesRepository.findByTeamId(team.id)
}