If you are using scalaz, I would use a combination of Option and ApplicativeBuilder |@| . If any of the inputs is None , then the result is also None .
import scalaz.std.option.optionInstance import scalaz.syntax.apply._ val result: Option[String] = Some(1) |@| Some("a") |@| Some(true) apply { (int, str, bool) => s"int is $int, str is $str, bool is $bool" }
In pure scala, you can use flatMap as an option:
val result: Option[String] = for { a <- aOpt b <- bOpt c <- cOpt } yield s"$a $b $c"
I personally prefer the application because it is clear that the results are independent. for-blocks read to me like "first do it with a, then with b, then with c", while the applicative style is more like "with all a, b and c, do ..."
Another option with a tale is a sequence that inverts a structure like T[A[X]] into A[T[X]] for traced T and applicative A.
import scalaz.std.option.optionInstance import scalaz.std.list.listInstance import scalaz.syntax.traverse._ val list: List[Option[Int]] = List(Option(1), Option(4), Option(5)) val result: Option[List[Int]] = list.sequence
source share