scala - 如何理解traverse、traverseU和traverseM

标签 scala scalaz

我对traverse、traverseU和traverseM的使用案例感到困惑,我在scalaz网站上搜索了它,简单的代码示例:

 def sum(x: Int) = x + 1

 List(1,2,3).traverseU(sum)

它看起来类似于( map 和聚合):

List(1,2,3).map(sum).reduceLeft(_ + _)

我认为这比 traverseU 的要多,我只是想知道这 3 种方法有什么区别,最好有一些示例代码来展示区别

提前非常感谢

最佳答案

sequence 用于将应用效果聚集在一起。更具体地说,它可以让您将 F[G[A]]“翻转”为 G[F[A]],前提是 GApplicativeFTraversable。因此,我们可以使用它来“汇集”一堆 Applicative 效果(注意所有 Monad 都是 Applicative):

List(Future.successful(1), Future.successful(2)).sequence : Future[List[Int]]
// = Future.successful(List(1, 2))
List(4.set("abc"), 5.set("def")).sequence : Writer[String, List[Int]]
// = List(4, 5).set("abcdef")

traverse 相当于 map 然后 sequence,因此当您有一个返回 Applicative< 的函数时可以使用它 并且您只想获取 Applicative 的单个实例,而不是它们的列表:

def fetchPost(postId: Int): Future[String]
//Fetch each post, but we only want an overall `Future`, not a `List[Future]`
List(1, 2).traverse[Future, String](fetchPost): Future[List[String]]

traverseUtraverse 操作相同,只是类型表示方式不同,以便编译器更容易推断它们。

def logConversion(s: String): Writer[Vector[String], Int] =
  s.toInt.set(Vector(s"Converted $s"))
List("4", "5").traverseU(logConversion): Writer[Vector[String], List[Int]]
// = List("4", "5").map(logConversion).sequence
// = List(4.set("Converted 4"), 5.set("Converted 5")).sequence
// = List(4, 5).set(Vector("Converted 4", "Converted 5"))

traverseM(f) 相当于 traverse(f).map(_.join),其中 join 是 scalaz 名称压平。它作为一种“提升平面 map ”很有用:

def multiples(i: Int): Future[List[Int]] =
  Future.successful(List(i, i * 2, i * 3))
List(1, 10).map(multiples): List[Future[List[Int]]] //hard to work with
List(1, 10).traverseM(multiples): Future[List[Int]]
// = List(1, 10).traverse(multiples).map(_.flatten)
// = List(1, 10).map(multiples).sequence.map(_.flatten)
// = List(Future.successful(List(1, 2, 3)), Future.successful(List(10, 20, 30)))
//     .sequence.map(_.flatten)
// = Future.successful(List(List(1, 2, 3), List(10, 20, 30))).map(_.flatten)
// = Future.successful(List(1, 2, 3, 10, 20, 30))

关于scala - 如何理解traverse、traverseU和traverseM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26602611/

相关文章:

scala - Kleisli 是仿函数、应用函数还是单子(monad)?

scala - 为什么Spark的 “Detected cartesian product for INNER join between logical plans”失败?

scala - 在函数外部导入 scalaz monad 语法

scala - 在Play上使用HAML,Scaml或Jade

java - 压缩:在Java/Scala中以指定比特率保存JPEG图像

scala - 使用返回 future 的函数遍历列表和流

scalaz - 使用 specs2 和 scalaz-scalacheck-binding 来测试法律

scala - 为什么 getOrElse 会丢失 scalaz 中的类型推断

java - 从进程名称获取进程ID

scala - UDAF Spark 中的多列输出