结合`OptionT`和`EitherT`来处理`Future [[Error,Option [T]]]`

时间:2017-12-28 16:18:48

标签: scala scalaz scala-cats

我想使用Cats EitherTOptionT来处理类型Future[Either[Error, Option[T]]。假设有以下方法:

def findTeacher(id: Int): Future[Either[String, Option[Teacher]]]
def findSchool(teacher: Teacher): Future[Either[String, Option[School]]]

现在,如果我想在后面打电话给他们,我可以像这样使用EitherTOptionT

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
}

我想知道是否可以通过将OptionTEitherT相结合来使其更简洁?

1 个答案:

答案 0 :(得分:6)

如果正确理解您的问题,您希望构建OptionTtype 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

不幸的是,即使implicitvar string = params.toString(); string = string.replace(/^.{12}/g,'************'); return string; ,你仍然需要在for-comprehension的第一行明确地写出它,但是这允许在更多的行上跳过它。