Search code examples
scalascalazapplicativescala-cats

Can we reverse Applicative of List?


I'm reading about scalaz and noticed that we can make a list of Applicatives to be an Applicative of List.

def sequenceA[F[_]: Applicative, A](list: List[F[A]]): F[List[A]] = list match {
         case Nil     => (Nil: List[A]).point[F]
         case x :: xs => (x |@| sequenceA(xs)) {_ :: _} 
       }

The question is can we do the opposite? Can we transform F[List[A]] to List[F[A]]?


Solution

  • This is possible if the F in question is Traversable. The code you're showing is specialized for List, but in fact it holds for all Traversable functors.

    This means, that for every F that's Traversable and any G that's Applicative, we can go from F[G[A]] to G[F[A]] with sequence.

    List also has an Applicative, so we can use it as our G, whereas in your example List was used as the F, the Traversable functor.

    An example where what you're asking works could be Option. Here's the original direction:

    val x: List[Option[Int]] = ...
    val y: Option[List[Int]] = x.sequence
    

    and the other direction:

    val a: Option[List[Int]] = ...
    val b: List[Option[Int]] = a.sequence
    

    We could also write another function specializing to List:

    def sequenceT[F[_]: Traverse, A](list: F[List[A]]): List[F[A]] = ...