3

What is the cleanest way in Scala to convert from Future[Option[Future[Int]]] to Future[Option[Int]]? Is it even possible?

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
Chris Stewart
  • 1,641
  • 2
  • 28
  • 60
  • 1
    If you ever decide to go the scalaz route, this is the kind of thing that monad transformers are good for. I think `OptionT[Task, Int]` would help you here. Related: http://stackoverflow.com/a/14386670/402884 – Chris Martin Aug 11 '15 at 03:19

3 Answers3

11

There are two nested Futures that you roll into one, so this calls for a flatMap.

def flatten[A](f: Future[Option[Future[A]]]): Future[Option[A]] =
  f.flatMap({
    case None => Future.successful(None)
    case Some(g) => g.map(Some(_))
  })

Or, more concisely:

def flatten[A](f: Future[Option[Future[A]]]): Future[Option[A]] =
  f.flatMap(o => Future.sequence(o.toSeq).map(_.headOption))

Thanks to @lmm's answer for the idea on that. Ideally this could be written as f.flatMap(Future.sequence), but unfortunately sequence expects a TraversableOnce, which Option does not extend.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
1

The cleanest way is probably using scalaz:

import scalaz.std.option._
import scalaz.std.scalaFuture._
import scalaz.syntax.traverse._

//assuming implicit execution context in scope

f.flatMap(_.sequence)
Community
  • 1
  • 1
lmm
  • 17,386
  • 3
  • 26
  • 37
0

You are asking how to code your way out of some paper bag, and you have gotten some good answers about how to do this, however you should be stepping back and trying to just not get into the paper bag you are currently in. See my answer here: Get rid of Scala Future nesting about how to avoid getting into a Future[X[Future[y]] type signature so that you don't have to figure out how to then get out of it.

Community
  • 1
  • 1
stew
  • 11,276
  • 36
  • 49