2017-07-27 15 views
3

私は2つのメソッドを持っていて、Future [String [T]]のどちらにも返しています。私はScala 2.12を使用しています。例えばScala 2.12 FutureとEitherの組み合わせ(バイアスされたバージョン)

機能は将来のいずれかの組み合わせを返さない場合は、私は単に理解のために、次のように行うことができます。

def convert(a, b) = ??? 
def callA(): Future[A] = ??? 
def callB(a: A): Future[B] = ??? 

def chain: Future[C] = for { 
    a <- callA 
    b <- callB(a) 
} yield convert(a, b) 

ただし、次の構文を使用してエラーをキャプチャし、最終結果に伝播したいと考えています。それを達成するための最善の方法は何ですか?また、callBまたはcallB1を使用する必要がありますか?

def convert(a, b): Future[Either[String, C]] = ??? 
def callA(): Future[Either[String, A]] = ??? 
def callB(a: A): Future[Either[String, B]] = ??? or 
def callB1(eithera: Either[String, A]): Future[Either[String, B]] = ??? 

catsトランスフォームモナドを使用すると、これを簡略化できます。ようこそ私に標準的なlibとcatの両方を使用するためのソリューションを与えるために。

+1

あなたは、単に 'Either'を使用している場合私が想定している 'String'を返す' Left'はエラーを含むテキストメッセージです。 'Success'と' Failure'を 'Future'に組み込んでみませんか? – Yaneeve

+2

'cats.'や' scalaz'から 'EitherT'を見てみたいと思うかもしれません。 – jilen

+0

@ Yaneeve私はただ簡単にしたいのですが、実際にはカスタマイズされたエラーオブジェクトです。 – ttt

答えて

5

コメントに記載されているように、これは猫とスカラが処理できるものです。しかし、私はまた、かなり小さいロジックに別の依存関係や複雑さを導入したくないという欲求を理解することができます。ここでは、それを自分で実装する場合、あなたは何ができるかです:適切なタイプでmapflatMapを実装

implicit class FutureEither[A](val wrapped: Future[Either[String, A]])(implicit ec: ExecutionContext) { 
    def map[B](f: A => B): FutureEither[B] = wrapped.map(_.map(f)) 

    def flatMap[B](f: A => FutureEither[B]): FutureEither[B] = wrapped.flatMap { 
    case Left(s) => Future(Left(s)) 
    case Right(a) => f(a).wrapped 
    } 
} 

がfor-理解のまったく同じスタイルを可能にします:

def convert(a: A, b: B): C = ??? 
def callA(): FutureEither[A] = ??? 
def callB(a: A): FutureEither[B] = ??? 

def chain: FutureEither[C] = for { 
    a <- callA() 
    b <- callB(a) 
} yield convert(a, b) 
+0

質問は 'FutureEither [C]'を 'Future [String、C]]のどちらに変換するのですか?ありがとう。 – ttt

+0

'.wrapped'を実行してください –

関連する問題