2014-10-02 13 views
7

zu erhalten Ist es möglich, eine List[F[G[A]]] in F[G[List[A]]] umzuwandeln?Wie führe ich die Sequenz über die Liste [F [G [A]]], um F [G [Liste [A]]]

Ich kann dies tun in Scalaz die folgende Art und Weise:

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

Ich frage mich nur, wenn es eine schönere Art und Weise, dies zu tun, anstatt .sequenceU.map(_.sequenceU) Vielleicht einen Monade Transformator? Ich habe das versucht, ohne viel Glück.

Antwort

5

Monad-Transformatoren sind der Weg zu gehen, wenn Sie die verschachtelte Sequenzierung vermeiden wollen. In diesem Fall sollten Sie eine OptionT[Future, A] (die Future[Option[A]] entspricht):

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 

Und dann:

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

scala> sequencedYs.foreach(println) 
None 

Wie erwartet.

+0

Es ist ziemlich offensichtlich, wenn man darüber nachdenkt, wirklich :) Danke. –

0

Ich habe erkannt, dass, während ein Monade Transformator hier ist groß, ich Vorteil nehmen, die applicatives komponieren:

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) 

Und dann:

scala> future.foreach(println) 
Some(List(1, 2)) 
+0

Was Lars damals natürlich vorgeschlagen hat, hat mir dann aber nicht geklickt. https://twitter.com/larsr_h/status/517997668866723840 –