2017-02-23 68 views
2

我写了这个代码发现:scala.concurrent.Future [选项[INT]]需要:[?]选项

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) 

        ^

回答

4

的问题是,在为理解从发电机获得的第一个元素 - x - 是一个Option,而另一些Future秒。不幸的是,Scala不支持在理解中使用不同的生成器类型,您需要一个monad变换器来实现这一点。

简单的方式就是包裹在未来的选项:

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

我希望帮助。

+0

这和我写的代码不一样。 m1和m2接受一个I​​nt ...不是一些(int) –

+0

正确的,你可以使用模式匹配来获取只有当它存在的值。我现在编辑它。 –

+0

如果你这样做,可以考虑使用'Future.successful(Some(3))'而不是'Future(一些(3))'。后者引入了不必要的异步边界并且需要存在'ExecutionContext',而前者只是构建了一个成功的'Future'实例。 – Haspemulator

1

您收到此错误,因为用于表达正被翻译成的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] 

未来是不是一种选择,例如,也不GenTraversableOnce所以它是不可能用于理解它,改造后的代码类似于以下内容:

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

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