、 、および の4 つの型A、型の初期値、および、 、および の 3 つの関数があります。BCDxFuture[Option[A]]f1: A => Option[B]f2: B => Future[Option[C]]f3: C => D
3 つの関数の "構成" となる型の値になるという結果forから始まる内包表記を作成するにはどうすればよいでしょうか?xFuture[Option[D]]
、 、および の4 つの型A、型の初期値、および、 、および の 3 つの関数があります。BCDxFuture[Option[A]]f1: A => Option[B]f2: B => Future[Option[C]]f3: C => D
3 つの関数の "構成" となる型の値になるという結果forから始まる内包表記を作成するにはどうすればよいでしょうか?xFuture[Option[D]]
これには (Scalaz の) モナド変換子を使用できます。
import scalaz.OptionT
import scalaz.std.option._
import scalaz.syntax.monad._
val result: Future[Option[D]] = (for {
a <- OptionT(x)
b <- OptionT(f1(a).point[Future])
c <- OptionT(f2(b))
} yield f3(c)).run
のモナドインスタンスが必要になりますFuture。scalaz-contrib に 1 つあります。
これは必ずしも最良の解決策ではありませんが、私が思いついたものです。作業する一般的なタイプを見つけようとすることから始めました
type N[X, Y] = Option[X] => Future[Option[Y]]
f1...次に、 、f2、およびf3をその一般的な型に変換します。
val f1: (A => Option[B]) = ???
val f1N: N[A, B] = {
case None => Future.successful(None)
case Some(a) => Future.successful(f1(a))
}
val f2: (B => Future[Option[C]]) = ???
val f2N: N[B, C] = {
case None => Future.successful(None)
case Some(b) => f2(b)
}
val f3: C => D = ???
val f3N: N[C, D] = {
case None => Future.successful(None)
case Some(c) => Future.successful(Some(f3(c)))
}
f1N、f2N、およびを作成したのでf3N、見栄えの良い for 内包表記で使用できます。
val y: Future[Option[D]] = for {
aOpt <- x
bOpt <- f1N(aOpt)
cOpt <- f2N(bOpt)
dOpt <- f3N(cOpt)
} yield dOpt