2017-02-23 97 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 s. К сожалению, Scala не поддерживает разные типы генераторов для понимания, и для этого вам понадобится трансформатор монады.

Простой способ просто обернуть вариант в будущем:

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

Я надеюсь, что помогает.

+0

Это не то же самое, что и код, который я написал. m1 и m2 принимают Int ... not Some (int) –

+0

Правильно, вы можете использовать сопоставление образцов, чтобы получить значение только в том случае, если оно присутствует. Я отредактирую его прямо сейчас. –

+0

Если вы идете этим путем, рассмотрите возможность использования 'Future.successful (Some (3))' вместо 'Future (Some (3))'. Последний вводит ненужную асинхронную границу и требует наличия «ExecutionContext», тогда как первый просто создает готовый успешный экземпляр «Future». – Haspemulator

1

Вы получаете эту ошибку, потому что для выражения переводится в цепочку flatMap, map, filter, withFilter и foreach вызовов методов. Вообще говоря, выражение:

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] 

Будущее не является экземпляром Option, ни 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)) не соответствует flatMap. Надеюсь, мой ответ поможет понять для понимания.

Смежные вопросы