Подтвердить что ты не робот

Как понимать траверс, traverseU и traverseM

Я запутался в случае использования траверса, traverseU и traverseM, я искал его на веб-сайте scalaz, пример простого кода:

 def sum(x: Int) = x + 1

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

похоже, что он похож на (map и aggregate):

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

Я думаю, что это больше, чем для traverseU, мне просто интересно, в чем разница между этими тремя методами, было бы лучше, если у меня будет некоторый пример кода, чтобы показать разницу

Большое спасибо заранее

4b9b3361

Ответ 1

sequence используется для сбора аппликативных эффектов. Более конкретно, это позволяет вам перевернуть F[G[A]] на G[F[A]], если G is Applicative и F is Traversable. Поэтому мы можем использовать его для "сближения" с эффектом 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]]

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(_.join), где join - имя скаляса для flatten. Это полезно как своего рода "подъем flatMap":

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))