我想使用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]]]
现在,如果我想在后面打电话给他们,我可以像这样使用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
}
我想知道是否可以通过将OptionT
与EitherT
相结合来使其更简洁?
答案 0 :(得分:6)
如果正确理解您的问题,您希望构建OptionT
和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
}
}
的组合monad-transformer。使用Cats,您可以尝试这样的事情:
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
}
作为
OResult.apply
不幸的是,即使implicit
是var string = params.toString();
string = string.replace(/^.{12}/g,'************');
return string;
,你仍然需要在for-comprehension的第一行明确地写出它,但是这允许在更多的行上跳过它。