【问题标题】:Composing Futures and Options组成期货和期权
【发布时间】:2013-10-18 22:01:33
【问题描述】:

我有ABCD这四种类型,Future[Option[A]]类型的初始值x和三个函数:f1: A => Option[B]f2: B => Future[Option[C]]f3: C => D .

我如何编写一个以x 开头的for 理解,它产生一个Future[Option[D]] 类型的值,这将是三个函数的“组合”?

【问题讨论】:

    标签: scala functional-programming for-comprehension


    【解决方案1】:

    您可以为此使用 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 中有一个。

    【讨论】:

    • 谢谢!如果以下问题看起来像一个愚蠢的问题,我很抱歉:我设法使用 Future{f1(a)} 而不是 f1(a).point[Future] 编译它。有什么区别吗?我应该使用什么选项的实现?
    • Scalaz 包含Option 的类型类,但我省略了已修复的导入。你会想使用Future.successful(f1(a))(这和f1(a).point[Future]做同样的事情)而不是Future{f1(a)},因为前者创造了一个已经实现的未来,而后者将异步运行f1(a),这是不必要的。
    【解决方案2】:

    这不一定是最佳解决方案,但这是我想出的。 我首先尝试找到一种常见的类型来使用

    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
    

    【讨论】:

      猜你喜欢
      • 2020-07-17
      • 2021-07-26
      • 2019-07-21
      • 2016-11-03
      • 2014-01-06
      • 2013-06-29
      • 2019-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多