Knows Not Much
Knows Not Much

Reputation: 31586

found: scala.concurrent.Future[Option[Int]] required: Option[?]

I have written this code

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

My objective is that the code should first open the future of m1 and if that has a some, then use that value. otherwise, it should open the future of m2 and use that value.

But it keeps getting a compile time error

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

                    ^

Upvotes: 2

Views: 2287

Answers (2)

Andrei T.
Andrei T.

Reputation: 2480

The problem is that in the for comprehension the first element obtained from the generator - x - is an Option, while the others are Futures. Unfortunately Scala doesn't support having different generator types in the same for comprehension and you would need a monad transformer to achieve this.

The simple way is just to wrap the Option in a Future:

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

I hope that helps.

Upvotes: 4

L.Lampart
L.Lampart

Reputation: 755

You are receiving this error because for expression is being translated to chain of flatMap, map, filter, withFilter and foreach method calls. Generally speaking expression:

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

Is translated to code somewhat similar to the following:

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

I simplified it a bit, in reality partial function are used but general idea remains the same. Option has the following signature of flatMap method:

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

Future is not an Option instance nor GenTraversableOnce so it is impossible to use for comprehension for it, your code after transformation looks similar to the following:

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

Type of m1(x).flatMap(x1 => m2(x1).map(x2 => x1 orElse x2)) is Future[Option[Int]] which does not conform to the flatMap signature. I hope my answer will help understand for comprehension.

Upvotes: 1

Related Questions