我有A
,B
,C
和D
四种类型,x
类型的初始值Future[Option[A]]
和三个函数:f1: A => Option[B]
,f2: B => Future[Option[C]]
和f3: C => D
。
如何编写以for
开头的x
理解,导致类型为Future[Option[D]]
的值为三个函数的“组合”?
答案 0 :(得分:5)
你可以使用monad变换器(来自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
你需要一个monad实例; scalaz-contrib中有一个。
答案 1 :(得分: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
,我可以将它们用于一个漂亮的理解中。
val y: Future[Option[D]] = for {
aOpt <- x
bOpt <- f1N(aOpt)
cOpt <- f2N(bOpt)
dOpt <- f3N(cOpt)
} yield dOpt