2017-02-23 83 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簽名。 我希望我的回答能幫助理解理解。