Convert a List of Options to an Option of List using Scalaz
Starting Scala 2.13
, and the addition of the Option::unless
builder to the standard library, a variant to Rex Kerr's answer would be:
Option.unless(list contains None)(list.flatten)
// val list = List(Some(1), Some(2)) => Some(List(1, 2))
// val list = List(Some(1), None, Some(2)) => None
or, if performance is at stake (in order to avoid flatten
's implicit conversion from Option
to List
):
Option.unless(list contains None)(list.map(_.get))
For some reason you dislike
if (lo.exists(_ isEmpty)) None else Some(lo.map(_.get))
? That's probably the shortest in Scala without Scalaz.
There's a function that turns a List[Option[A]]
into an Option[List[A]]
in Scalaz. It's sequence
. To get None
in case any of the elements are None
and a Some[List[A]]
in case all the elements are Some
, you can just do this:
import scalaz.syntax.traverse._
import scalaz.std.list._
import scalaz.std.option._
lo.sequence
This method actually turns F[G[A]
into G[F[A]]
given that there exists an implementation of Traverse[F]
, and of Applicative[G]
(Option
and List
happen to satisfy both and are provided by those imports).
The semantics of Applicative[Option]
are such that if any of the elements of a List
of Option
s are None
, then the sequence
will be None
as well. If you want to get a list of all the Some
values regardless of whether any other values are None
, you can do this:
lo flatMap (_.toList)
You can generalize that for any Monad
that also forms a Monoid
(List
happens to be one of these):
import scalaz.syntax.monad._
def somes[F[_],A](x: F[Option[A]])
(implicit m: Monad[F], z: Monoid[F[A]]) =
x flatMap (o => o.fold(_.pure[F])(z.zero))