是否可以很好地将List[F[G[A]]]
转换为F[G[List[A]]]
?
我可以通过以下方式在Scalaz中执行此操作:
val x: List[Future[Option[Int]]] = ???
val transformed: Future[Option[List[Int]]] = x.sequenceU.map(_.sequenceU)
我只是想知道是否有更好的方法来做这个而不是.sequenceU.map(_.sequenceU)
也许使用monad变换器?我确实尝试了这一点,没有太多运气。
答案 0 :(得分:5)
如果你想避免嵌套测序,Monad变换器就是你的选择。在这种情况下,您需要OptionT[Future, A]
(相当于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
然后:
scala> sequencedXs.foreach(println)
Some(List(1, 2))
scala> sequencedYs.foreach(println)
None
正如所料。
答案 1 :(得分:0)
我已经意识到虽然monad变换器在这里非常棒,但我可以利用应用程序的组成:
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)
然后:
scala> future.foreach(println)
Some(List(1, 2))