2014-10-02 18 views
7

Có thể biến đổi List[F[G[A]]] thành F[G[List[A]]] độc đáo không?Làm thế nào để chạy chuỗi trên Danh sách [F [G [A]]] để lấy F [G [Danh sách [A]]]

tôi có thể làm điều này trong Scalaz theo cách sau:

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

Tôi chỉ tự hỏi nếu có một cách đẹp hơn để làm điều này chứ không phải là .sequenceU.map(_.sequenceU) Có lẽ sử dụng một máy biến áp đơn nguyên? Tôi đã cố gắng này, mà không có nhiều may mắn.

Trả lời

5

Biến thế đơn nguyên là cách để đi nếu bạn muốn tránh trình tự lồng nhau. Trong trường hợp này bạn muốn một OptionT[Future, A] (tương đương với 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 

Và sau đó:

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

scala> sequencedYs.foreach(println) 
None 

Đúng như dự đoán.

+0

Đó là khá rõ ràng khi bạn nghĩ về nó, rất cảm ơn. –

0

tôi đã nhận ra rằng trong khi một biến đơn nguyên là tuyệt vời ở đây, tôi có thể tận dụng lợi thế đó applicatives soạn:

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) 

Và sau đó:

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

Mà, tất nhiên, Lars đề nghị vào thời điểm đó, nhưng nó đã không bấm cho tôi sau đó. https://twitter.com/larsr_h/status/517997668866723840 –

Các vấn đề liên quan