Given a Option[Future[Option[Int]]]
:
scala> val x: Option[Future[Option[Int]]] = Some ( Future ( Some ( 10 ) ) )
x: Option[scala.concurrent.Future[Option[Int]]] =
Some(scala.concurrent.impl.Promise$DefaultPromise@446a1e84)
I want Future[Option[Int]]
.
I can pattern match (or use Option#getOrElse
):
scala> x match {
| case Some(f) => f
| case None => Future { None }
| }
res6: scala.concurrent.Future[Option[Int]] =
scala.concurrent.impl.Promise$DefaultPromise@446a1e84
scala> res6.value
res7: Option[scala.util.Try[Option[Int]]] = Some(Success(Some(10)))
But, is there a higher-order function that will do the job?
I thought of using sequence
, but I don't have an outer type of List
:
> :t sequence
sequence :: Monad m => [m a] -> m [a]
Haskell's sequence
isn't as generic as it could be, or as generic as Scalaz's (and I'm assuming you're okay with a Scalaz solution since you mention sequence
).
Scalaz's sequence
(and Haskell's sequenceA
in Data.Traversable
) only requires that the outer type constructor have a Traverse
instance—it doesn't necessarily have to be a list. Option
has a Traverse
instance, so sequence
will work just fine here:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scalaz._, Scalaz._
def collapse(x: Option[Future[Option[Int]]]): Future[Option[Int]] =
x.sequence.map(_.flatten)
Scalaz also provides an orZero
extension method for Option
, which would allow you just to write x.orZero
, since the zero of Future[Option[Int]]
is Future(None)
.
I'd actually probably use x.getOrElse(Future.successful(None))
, though, in this case—it's slightly (probably irrelevantly) more performant, but more importantly it's as clear and almost as concise as the Scalaz options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With