How to run sequence over List[F[G[A]]] to get F[G[List[A]]]
Asked Answered
I

2

7

Is it possible to transform a List[F[G[A]]] into F[G[List[A]]] nicely?

I can do this in Scalaz the following way:

val x: List[Future[Option[Int]]] = ???
val transformed: Future[Option[List[Int]]] = x.sequenceU.map(_.sequenceU)

I'm just wondering if there's a nicer way to do this rather than .sequenceU.map(_.sequenceU) Perhaps using a monad transformer? I did attempt this, without much luck.

Insinuation answered 2/10, 2014 at 14:54 Comment(0)
P
5

Monad transformers are the way to go if you want to avoid the nested sequencing. In this case you want an OptionT[Future, A] (which is equivalent to Future[Option[A]]):

import scalaz._, Scalaz._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

val xs = List(OptionT(Future(some(1))), OptionT(Future(some(2))))
val ys = OptionT(Future(none[Int])) :: xs

val sequencedXs: Future[Option[List[Int]]] = xs.sequenceU.run
val sequencedYs: Future[Option[List[Int]]] = ys.sequenceU.run

And then:

scala> sequencedXs.foreach(println)
Some(List(1, 2))

scala> sequencedYs.foreach(println)
None

As expected.

Prophylactic answered 2/10, 2014 at 17:24 Comment(1)
It's quite obvious when you think about it, really :) Thanks.Insinuation
I
0

I've realised that while a monad transformer is great here, I can take advantage that applicatives compose:

def transform[F[_], G[_], A](list: List[F[G[A]]])(implicit af: Applicative[F], ao: Applicative[G]): F[G[List[A]]] = {
  type λ[α] = F[G[α]]
  implicit val applicative: Applicative[λ] = af compose ao
  list.sequence[λ, A]
}
val lfo:    List[Future[Option[Int]]] = List(Future(1.some), Future(2.some))
val future: Future[Option[List[Int]]] = transform(lfo)

And then:

scala> future.foreach(println)
Some(List(1, 2))
Insinuation answered 27/10, 2014 at 20:44 Comment(1)
Which, of course, Lars suggested at the time, but it didn't click for me then. twitter.com/larsr_h/status/517997668866723840Insinuation

© 2022 - 2024 — McMap. All rights reserved.