Je suis confus au sujet du cas d'utilisation de traverse, traverseU et traverseM, je l'ai recherché sur le site Web de scalaz, l'exemple de code simple:
def sum(x: Int) = x + 1
List(1,2,3).traverseU(sum)
il ressemble à (carte et agrégat):
List(1,2,3).map(sum).reduceLeft(_ + _)
Je pense que c'est plus que cela pour traverseU, je me demande juste quelle est la différence entre ces 3 méthodes, il vaudrait mieux que j'aie un exemple de code pour montrer la différence
Merci d'avance
sequence
est utilisé pour rassembler les effets applicatifs. Plus concrètement, il vous permet de "basculer" F[G[A]]
Vers G[F[A]]
, À condition que G
soit Applicative
et F
soit Traversable
. Nous pouvons donc l'utiliser pour "rassembler" un tas d'effets Applicative
(notez que tous les Monad
sont 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
est équivalent à map
puis sequence
, vous pouvez donc l'utiliser lorsque vous avez une fonction qui renvoie un Applicative
et que vous souhaitez simplement en obtenir un seul instance de votre Applicative
plutôt qu'une liste d'entre eux:
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
est la même opération que traverse
, juste avec les types exprimés différemment pour que le compilateur puisse les déduire plus facilement.
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)
est équivalent à traverse(f).map(_.join)
, où join
est le nom scalaz pour flatten
. Il est utile comme une sorte de "lifting 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))