1

Does this function (or perhaps some monadic generalisation of it) have an established name?

def foo[T](in: Seq[Option[T]]): Option[Seq[T]] = {
    val res = in.flatten.seq
    if (res.length == in.length) Some(res) else None
}

Is there a more elegant implementation?

Joe Halliwell
  • 1,155
  • 6
  • 21
  • 2
    It's usually called "sequence" (have a look at Future.sequence for instance) https://www.haskell.org/hoogle/?hoogle=sequence Read this for info about the scalaz implementation: http://eed3si9n.com/learning-scalaz-day12 – Giovanni Caporaletti Feb 27 '16 at 10:26
  • See also my answer [here](http://stackoverflow.com/a/12358892/334519). – Travis Brown Feb 27 '16 at 13:30

1 Answers1

3

As already suggested in the comments, the function from Seq[M[A]] to M[Seq[A]] (where M is a monad) is usually referred to as sequence.

The Haskell definition of it is:

Evaluate each action in the sequence from left to right, and collect the results.

There's no generic implementation of it in the scala standard library, but you can see an example for the Future type here: https://github.com/scala/scala/blob/v2.10.3/src/library/scala/concurrent/Future.scala#L487-L491

You can find generic implementations of sequence in libraries such as cats or scalaz.

One thing to notice, is that sequence is a specific case of a more generic operation, usually called traverse.

Haskell defines traverse as

Map each element of a structure to an action, evaluate these actions from left to right, and ignore the results.

Now, given the definition, sequence can be implemented in terms of traverse, simply by using the identity function (x => x) as the map operation of traverse.

If you take a look at the implementations mentioned above, you'll find that they all leverage this generalization and they all use traverse to implement sequence.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235