Scala 如何理解traverse、traverseU和traverseM

Scala 如何理解traverse、traverseU和traverseM,scala,scalaz,Scala,Scalaz,我对traverse、traverseU和traverseM的用法感到困惑,我在scalaz网站上搜索了它,简单的代码示例: def sum(x: Int) = x + 1 List(1,2,3).traverseU(sum) 它看起来类似于(映射和聚合): 我认为这比traverseU更重要,我只是想知道这3种方法之间的区别是什么,最好我会有一些示例代码来说明区别 提前致谢序列用于收集应用效果。更具体地说,它允许您将F[G[A]翻转到G[F[A],前提是G是Applicative且F是

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

 def sum(x: Int) = x + 1

 List(1,2,3).traverseU(sum)
它看起来类似于(映射和聚合):

我认为这比traverseU更重要,我只是想知道这3种方法之间的区别是什么,最好我会有一些示例代码来说明区别


提前致谢

序列
用于收集应用效果。更具体地说,它允许您将
F[G[A]
翻转到
G[F[A]
,前提是
G
Applicative
F
可遍历的。因此,我们可以使用它来“聚合”一组
Applicative
效果(注意所有
Monad
s都是
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]]
traverseU
traverse
的操作相同,只是类型表达不同,以便编译器更容易推断它们

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(u.join)
,其中
join
flatten
的scalaz名称。它作为一种“提升平面图”很有用:


谢谢,我赞成,所以我只是想知道你提到了traverse和traverseU之间的区别是类型推断,这是唯一的区别,因为就我而言,我将只使用traverseU而不是TraverseEyes,这是唯一的区别。(从技术上讲,它使用一个额外的参数来执行推断,但我希望JVM能够对此进行优化)。如果
traverseU
无法推断类型参数,您需要手动指定它们(或者如果您正在编写泛型代码,而您所遍历的类型本身就是一个类型参数),则使用
traverse
更容易(它没有推断辅助程序),但我认为这是唯一一种你想使用
traverse
而不是
traverseU
的情况。顺便说一句,我认为代码应该是Future.now而不是Future.successful,因为前一个代码来自scalaz,因此它具有隐式值,但是,标准库中的后一个没有隐式解析。我相信,如果您在范围内(从
scalaz.std
中的某个地方)有适当的导入,那么标准库
将来的
就有实例。
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]]
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"))
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))