结合列表,未来和选择的理解 - scalaz

时间:2016-02-29 17:47:38

标签: scala monads scalaz monad-transformers

我遇到了以下问题:

val sth: Future[Seq[T, S]] = for {
  x <- whatever: Future[List[T]]
  y <- x: List[T]
  z <- f(y): Future[Option[S]]
  n <- z: Option[S]
} yield y: T -> n: S

我想让这段代码发挥作用(我想每个人都理解这个想法,因为我已经添加了类型)。

通过&#34;工作&#34;我的意思是,我希望继续使用for-comprehension结构并最终实现预期的类型。我知道有&#34;丑陋&#34;如何做到这一点,但我想学习如何做到这一点:)

当我阅读互联网时,我已经得出结论,我的问题可以通过monad变换器解决。 scalaz。不幸的是,我找不到一个例子来帮助我更好地理解我应该如何继续。

目前我已尝试过scalaz和Eff monad libs,但我想我仍然不明白它是如何工作的,因为我无法解决我的问题。

我将不胜感激任何帮助。

编辑:它应该是序列的未来,也是关于&#34;无论什么&#34;我把它作为函数的参数,很抱歉误导你

2 个答案:

答案 0 :(得分:1)

您可以使用scalaz ListT monad transformer

执行所需的操作
 object Test {
   import scalaz._
   import ListT._
   type T = String
   type S = Int
   val whatever: Future[List[T]] = ??? // you get this somewhere
   def f(y: T): Future[Option[S]] = ??? // function that returns future of option

   val sth: Future[List[(T, S)]] = (for {
     y <- listT(whatever) 
     // you cannot mix list and option, but you can convert the option to a list of 1 item
     n <- listT(f(y).map(_.toList)) 
   } yield y -> n).run
 }

N.B。:既然你从未来开始,你就不能返回Seq [(T,S)],你只能拥有未来。如果要阻止并获得结果,则必须调用Await.result。

答案 1 :(得分:1)

for理解的问题在于它不是某种神奇的monadic&#34; unwrapper&#34;,它只是map的序列,{ {1}}和flatMap

您可能知道filtermap仅在&#34;内部&#34;类型,离开&#34;外部&#34; monad的类型不变。这意味着您无法执行此操作:

flatMap

在单for { x <- whatever: Future[List[T]] y <- x: List[T] } yield y 内。相反,你可以做这样的事情:

for

看起来有点难看。

回到你的情况,我更容易使用for (x <- whatever: Future[List[T]]) yield for (y <- x: List[T]) yield y map明确地编写整个转换,因为它为你提供了更大的可见性和控制力:

flatMap

另外,@ trustnoone提到,如果没有明确调用whatever.flatMap { x: List[T] => Future.sequence(x.map { y: T => f(y).map(y -> _) }).map(_.collect { case (y, Some(n)) => y -> n }) } ,你就无法摆脱Future