2014-10-02 17 views
7

È possibile trasformare un List[F[G[A]]] in F[G[List[A]]] in modo corretto?Come eseguire la sequenza su Elenco [F [G [A]]] per ottenere F [G [Elenco [A]]]

posso fare questo nel Scalaz seguente modo:

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

Mi chiedo solo se c'è un modo migliore per fare questo, piuttosto che .sequenceU.map(_.sequenceU) Forse usando un trasformatore monade? L'ho provato, senza molta fortuna.

risposta

5

I trasformatori Monad sono la soluzione ideale se si desidera evitare il sequenziamento nidificato. In questo caso si desidera un OptionT[Future, A] (che equivale 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 

E poi:

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

scala> sequencedYs.foreach(println) 
None 

come previsto.

+0

E 'abbastanza evidente quando si pensa a questo proposito, grazie davvero. –

0

mi sono reso conto che, mentre un trasformatore di monade è grande qui, posso prendere vantaggio che applicativi comporre:

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) 

E poi:

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

Che, naturalmente, Lars ha suggerito al momento, ma non ha cliccato per me allora. https://twitter.com/larsr_h/status/517997668866723840 –

Problemi correlati