web-dev-qa-db-ja.com

トラバース、traverseUおよびtraverseMを理解する方法

Traverse、traverseU、traverseMの使用例について混乱しています。単純なコード例であるscalaz Webサイトで検索しました。

 def sum(x: Int) = x + 1

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

(map and aggregate)に似ているように見えます:

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

TraverseUの場合はそれ以上だと思います。これらの3つの方法の違いは何だろうと思います。違いを示すサンプルコードを用意しておくとよいでしょう。

事前に感謝します

38
Xiaohe Dong

sequence適用可能な効果をまとめるに使用されます。より具体的には、GApplicativeFTraversableであれば、_F[G[A]]_を_G[F[A]]_に「反転」できます。したがって、これを使用して一連のApplicative効果を「引き寄せ」ます(Monadsはすべて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")
_

traversemapの次に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)と同等です。ここで、joinflattenのスカラー名です。 「リフティング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))
_
72
lmm