2014-10-02 11 views
7

Czy można dobrze przekształcić List[F[G[A]]] w F[G[List[A]]]?Jak uruchomić sekwencję na liście [F [G [A]]], aby uzyskać F [G [List [A]]]

mogę to zrobić w Scalaz następujący sposób:

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

Zastanawiam się, czy jest jakiś sposób na to ładniejszy niż .sequenceU.map(_.sequenceU) zrobić Być może za pomocą transformatora monady? Próbowałem tego, bez większego powodzenia.

Odpowiedz

5

Transformatory monadowe są sposobem na uniknięcie zagnieżdżonego sekwencjonowania. W tym przypadku, gdy chcesz się OptionT[Future, A] (co jest równoważne 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 

, a następnie:

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

scala> sequencedYs.foreach(println) 
None 

zgodnie z oczekiwaniami.

+0

Jest to dość oczywiste, gdy myślisz o tym, Naprawdę dzięki. –

0

zdałem sobie sprawę, że choć monada transformator jest wielki tutaj, mogę wziąć tę zaletę, że applicatives komponować:

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) 

, a następnie:

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

Co, oczywiście, zasugerował Lars, ale wtedy mnie nie kliknęło. https://twitter.com/larsr_h/status/517997668866723840 –

Powiązane problemy