Ami*_*imi 7 scala scalaz scala-cats
我想使用Cats EitherT
并OptionT
处理该类型Future[Either[Error, Option[T]]
.假设有以下方法:
def findTeacher(id: Int): Future[Either[String, Option[Teacher]]]
def findSchool(teacher: Teacher): Future[Either[String, Option[School]]]
Run Code Online (Sandbox Code Playgroud)
现在,如果我想随后在for-comprehension中调用它们,我可以使用EitherT
并OptionT
喜欢这样:
def getSchoolByTeacherId(id: Int): Future[Either[String, Option[School]]] = {
val result = for {
maybeTeacher <- EitherT(findTeacher(id))
schoolF = maybeTeacher.map(findSchool).getOrElse(Future.successful(Right(None)))
school <- EitherT(schoolF)
} yield {
school
}
result.value
}
Run Code Online (Sandbox Code Playgroud)
我不知道是否有可能通过合并,使之更简洁,也许OptionT
用EitherT
?
如果正确地理解你的问题,你想建立的组合单子变压器EitherT
和OptionT
.使用Cats,您可以尝试这样的事情:
type FutureEither[X] = EitherT[Future, String, X]
type OResult[X] = OptionT[FutureEither, X]
object OResult {
implicit def apply[A](value: Future[Either[String, Option[A]]]): OResult[A] = OptionT[FutureEither, A](EitherT(value))
implicit class OResultOps[A](val value: OResult[A]) extends AnyVal {
@inline
def directValue: Future[Either[String, Option[A]]] = value.value.value
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以重写你getSchoolByTeacherId
的
import OResult._
def getSchoolByTeacherId(id: Int): Future[Either[String, Option[School]]] = {
val result = for {
teacher <- OResult(findTeacher(id))
school <- findSchool(teacher)
} yield school
result.directValue
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,即使OResult.apply
是implicit
你仍然有它在你换理解的第一行明确写入但这允许跳过它的进一步线.