Это действительно хороший вопрос!
Вы хотите последовательно запустить flatMap
в списке элементов произвольного размера. Если вы не знаете, какой длины ваш список, вы можете обработать его с помощью рекурсии или, что то же самое, со сгибом.
scala> def sequence[A](lss: List[List[A]]) = lss.foldRight(List(List[A]())) {
| (m, n) => for (x <- m; xs <- n) yield x :: xs
| }
scala> sequence(List(List(1, 2), List(4, 5), List(7)))
res2: List[List[Int]] = List(List(1, 4, 7), List(1, 5, 7), List(2, 4, 7), List(2
, 5, 7))
(Если вы не можете разобраться в коде, не волнуйтесь, узнайте, как использовать Hoogle и украдите его у Haskell )
Это можно сделать с помощью Scalaz (обычно он начинается с F[G[X]]
и возвращает G[F[X]]
, учитывая, что конструкторы типов G
и F
имеют возможности Traverse
и Applicative
соответственно.
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> List(List(1, 2), List(4, 5), List(7)).sequence
res3: List[List[Int]] = List(List(1, 4, 7), List(1, 5, 7), List(2, 4, 7), List(2
, 5, 7))
scala> Seq(some(1), some(2)).sequence
res4: Option[Seq[Int]] = Some(List(1, 2))
scala> Seq(some(1), none[Int]).sequence
res5: Option[Seq[Int]] = None