2017-03-09 5 views
0

Wie kann ich "reparieren" diese Antwort, ich wollte Zukunft [Option [F4]]Wie viele Schichten der Zukunft Option Zukunft in der Antwort

val f4Response: Future[Option[Future[Option[Future[F4]]]]] = 
    for { 
     f1Opt <- api.getF1() // Future[Option[F1]] 
     f2Opt <- if (f1Opt.isDefined) api.getF2(f1Opt.get.id) else Future.successful(None) // getF2 is Future[Option[F3]] 
    } yield { 
     for { 
      f1 <- f1Opt 
      f2 <- f2Opt 
     } yield { 
      for { 
       f3Opt <- api.getF3(f1.id, f2.id) // Future[Option[F3]] 
      } yield { 
       for { 
        f3 <- f3Opt 
       } yield { 
        api.insertF(f1, f2, f3) // Future[Option[F4]] 
       } 
      } 
     } 
    } 

aktualisieren

Ich bin entfernen versuchen scalaz zu verwenden, aber ich erhalte eine Fehlermeldung:

val result: Future[Option[f4]] = (
      for { 
       f1 <- OptionT(api.getF1(..)) 
       f2 <- OptionT(api.getF2(..)) 
       f3 <- OptionT(api.getF3(f1.id, f2.id) 
      } yield api.getF4(f1, f2, f3) 
     ).run 

Fehler ist:

[error] found : scala.concurrent.Future[Option[scala.concurrent.Future[F4]]] 
[error] required: scala.concurrent.Future[Option[F4]] 

Auch kann ich nicht zugreifen f1.id und f2.id in der Zeile:

f3 <- OptionT(api.getF3(f1.id, f2.id) 

Antwort

1

Das ist die perfekte Lösung für catsOptionT Monade Transformator.

Sie müssen einige Katzen Importe:

import cats.data.OptionT 
import cats.instances.future._ 

lassen Sie uns sagen, dass dies Ihre Datenstruktur (verspottet):

case class F1(id: Int) 
case class F2(id: Int) 
case class F3(id: Int) 
trait F4 

object api { 
    def getF1(): Future[Option[F1]] = ??? 
    def getF2(f1: Int): Future[Option[F2]] = ??? 
    def getF3(f1: Int, f2: Int): Future[Option[F3]] = ??? 
    def insertF(f1: Int, f2: Int, f3: Int): Future[Option[F4]] = ??? 
} 

dann können Sie tun:

val resultT: OptionT[Future, F4] = for { 
    f1 <- OptionT(api.getF1()) 
    f2 <- OptionT(api.getF2(f1.id)) 
    f3 <- OptionT(api.getF3(f1.id, f2.id)) 
    f4 <- OptionT(api.insertF(f1.id, f2.id, f3.id)) 
} yield f4 

val result: Future[Option[F4]] = resultT.value 

Alternativ können Sie direkt Ihre Methoden wickeln mit OptionT:

type FutOpt[T] = OptionT[Future, T] 

def getF1(): FutOpt[F1] = OptionT { ??? } 
def getF2(f1: Int): FutOpt[F2] = OptionT { ??? } 
def getF3(f1: Int, f2: Int): FutOpt[F3] = OptionT { ??? } 
def insertF(f1: Int, f2: Int, f3: Int): FutOpt[F4] = OptionT { ??? } 

val resultT: FutOpt[F4] = for { 
    f1 <- api.getF1() 
    f2 <- api.getF2(f1.id) 
    f3 <- api.getF3(f1.id, f2.id) 
    f4 <- api.insertF(f1.id, f2.id, f3.id) 
} yield f4 

val result: Future[Option[F4]] = resultT.value 

Sie auch scalazOptionT halten genau die gleiche Syntax (mit Ausnahme .value ->.run) können nur durch Importe zu ändern .

import scalaz._ 
import Scalaz._ 

Mit def insertF(f1: Int, f2: Int, f3: Int): Future[F4] statt Future[Option[F4]] können Sie die für Verständnis neu zu schreiben (mit scalaz) als:

val resultT: OptionT[Future, F4] = for { 
    f1 <- OptionT(api.getF1()) 
    f2 <- OptionT(api.getF2(f1.id)) 
    f3 <- OptionT(api.getF3(f1.id, f2.id)) 
    f4 <- api.insertF(f1.id, f2.id, f3.id).liftM[OptionT] 
} yield f4 

val result: Future[Option[F4]] = resultT.run 
+0

hat catz OptionT das gleiche wie scalaz OptionT verhalten? – Blankman

+0

wenn ich versuche das mit scalaz zu tun, muss ich Probleme 1) Ich kann nicht f1.id, f2.id um f3 zu bekommen 2) es gibt Zukunft [Option [Zukunft [F4]] Ich füge hinzu, was ich habe jetzt meine Frage – Blankman

+1

fast, Sie müssen nur etwas Syntax ändern (zB 'Wert' ->' run'), ich werde ein 'scalaz' Beispiel liefern ... –

0
val f4Response: Future[Option[Int]] = api.getF1() flatMap { 
    case Some(f1) => { 
    api.getF2(f1).flatMap { 
     case Some(f2) => { 
     api.getF3(f1.id, f2.id).flatMap { 
      case Some(f3) => bar(f1, f2, f3) 
     } 
     } 
    } 
    } 
} 

for yield vielleicht ist es für dieses Szenario nicht notwendig patter match vielleicht besser ist, keine Option.get direkt (es wird vielleicht scheitern), es ist sicherer für pattern match.