2017-12-28 11 views
4

EitherTOptionTを使って、タイプFuture[Either[Error, Option[T]]を扱いたいと思います。次のメソッドを仮定:今すぐ`OptionT`と` EitherT`を組み合わせてFuture {[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の組み合わせですか?

+0

「OptionT」を使用することでどのような利点が期待できますか(あなたの例では使用しません)? –

+0

2つ目の理解の代わりに、より簡潔な方法を探しています。あるいは、私が気づいていないいくつかの方法やタイプの猫を使って別のやり方で書き直すことができます(必ずしもfor-comprehensionを使う必要はありません) –

答えて

4

あなたの質問を正しく理解している場合は、EitherTOptionTのモナドトランスフォーマーを組み立てたいとします。 OResult.applyは、あなたはまだ最初に明示的に記述する必要がありimplicitであっても、

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 
    } 

} 

そして、あなたの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 
} 

として再書き込み可能:あなたはこのような何かを試すことが猫を使いますあなたの理解のための行であるが、これはさらなる行でそれをスキップすることを可能にする。

関連する問題