2013-10-10 84 views
2

我有四种类型ABCD,类型Future[Option[A]]和三个函数的初始值xf1: A => Option[B]f2: B => Future[Option[C]]f3: C => D创作期货及期权

我该如何编写for理解,从x开始,导致Future[Option[D]]这个类型的值将是这三个函数的“组合”?

回答

5

您可以使用单子变压器(从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中。

+0

谢谢!如果以下内容看起来像一个愚蠢的问题,我很抱歉:我设法使用'Future {f1(a)}'而不是'f1(a).point [Future]'来编译它。有什么区别吗?我应该使用什么选项的实施? – miguel

+0

Scalaz包含'Option'的类型类,但我省略了我已修复的导入。你希望使用'Future.successful(f1(a))'(这与'f1(a).point [Future]')相同,而不是'Future {f1(a)}',因为前者创造一个已经实现的未来,而后者将异步运行'f1(a)',这是不必要的。 – Hugh

1

这不一定是最好的解决方案,但这是我想出的。 我开始试图找到一种常见的类型有

type N[X, Y] = Option[X] => Future[Option[Y]] 

工作...然后转换f1f2f3于普通型。

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))) 
} 

现在,我已经创建f1Nf2Nf3N,我可以在一个非常漂亮的换理解使用它们。

val y: Future[Option[D]] = for { 
    aOpt <- x 
    bOpt <- f1N(aOpt) 
    cOpt <- f2N(bOpt) 
    dOpt <- f3N(cOpt) 
} yield dOpt