【问题标题】:found: scala.concurrent.Future[Option[Int]] required: Option[?]找到:scala.concurrent.Future[Option[Int]] 需要:Option[?]
【发布时间】:2017-02-23 21:12:10
【问题描述】:

我已经写了这段代码

def m1(x: Int) = Future { if (x % 2 == 0) Some(x) else None }
def m2(x: Int) = Future { if (x % 2 != 0) Some(x) else None }

for {
  x <- Some(3)
  x1 <- m1(x)
  x2 <- m2(x)
} yield x1 orElse x2

我的目标是代码应该首先打开 m1 的未来,如果它有一些,然后使用那个值。否则,它应该打开 m2 的未来并使用该价值。

但它总是出现编译时错误

<console>:26: error: type mismatch;
 found   : scala.concurrent.Future[Option[Int]]
 required: Option[?]
       x1 : Option[Int] <- m1(x)

                    ^

【问题讨论】:

    标签: scala


    【解决方案1】:

    问题在于,在 for 理解中,从生成器获得的第一个元素 - x - 是 Option,而其他元素是 Futures。不幸的是,Scala 不支持在同一个生成器类型中使用不同的生成器类型以便理解,您需要一个 monad 转换器来实现这一点。

    简单的方法就是将 Option 包装在 Future 中:

    for {
      Some(x) <- Future.successful(Some(3))
      x1 <- m1(x)
      x2 <- m2(x)
    } yield x1 orElse x2
    

    希望对你有帮助。

    【讨论】:

    • 这和我写的代码不一样。 m1 和 m2 接受一个 Int ...不是 Some(int)
    • 对,您可以使用模式匹配来获取只有存在的值。我马上修改。
    • 如果你这样做,考虑使用Future.successful(Some(3))而不是Future(Some(3))。后者引入了不必要的异步边界,并且需要存在ExecutionContext,而前者只是构造了一个就绪成功的Future 实例。
    • @Haspemulator 谢谢,这是个好建议。我会用你的建议更新代码:)
    【解决方案2】:

    您收到此错误是因为 for 表达式正在转换为 flatMapmapfilterwithFilterforeach 方法调用的链。一般的表达方式:

    for {
      x <- X
      y <- Y
    } yield yourCode(x, y)
    

    被翻译成类似于以下的代码:

    X.flatMap(x => Y.map(y => yourFunc(x, y))
    

    我简化了一点,实际上使用了部分函数,​​但总体思路保持不变。 选项具有以下flatMap 方法的签名:

    def flatMap[B](f : A => Option[B]): Option[B]
    def flatMap[B](f : A => GenTraversableOnce[B]): Option[B]
    

    Future 不是 Option 实例,也不是 GenTraversableOnce,因此无法对其进行理解,转换后的代码如下所示:

    Some(3).flatMap(x => m1(x).flatMap(x1 => m2(x1).map(x2 => x1 orElse x2)))
    

    m1(x).flatMap(x1 =&gt; m2(x1).map(x2 =&gt; x1 orElse x2)) 的类型是 Future[Option[Int]],它不符合 flatMap 签名。 希望我的回答能帮助理解理解。

    【讨论】:

      猜你喜欢
      • 2015-11-03
      • 2017-09-20
      • 2019-03-03
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 2016-11-08
      • 2019-09-06
      相关资源
      最近更新 更多