Skip to content

Commit 90982b9

Browse files
committed
Optimize foldMap implementations with combineAll
1 parent aeff8a6 commit 90982b9

File tree

9 files changed

+28
-2
lines changed

9 files changed

+28
-2
lines changed

alleycats-core/src/main/scala/alleycats/std/iterable.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package alleycats
22
package std
33

4-
import cats.{Eval, Foldable}
4+
import cats.{Eval, Foldable, Monoid}
55
import export._
66

77
@reexports(IterableInstances)
@@ -16,6 +16,9 @@ object IterableInstances {
1616

1717
override def foldRight[A, B](fa: Iterable[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
1818
Foldable.iterateRight(fa, lb)(f)
19+
20+
override def foldMap[A, B](fa: Iterable[A])(f: A => B)(implicit B: Monoid[B]): B =
21+
B.combineAll(fa.iterator.map(f))
1922
}
2023

2124
}

alleycats-core/src/main/scala/alleycats/std/set.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ object SetInstances {
6868
def foldRight[A, B](fa: Set[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
6969
Foldable.iterateRight(fa, lb)(f)
7070

71+
override def foldMap[A, B](fa: Set[A])(f: A => B)(implicit B: Monoid[B]): B =
72+
B.combineAll(fa.map(f))
73+
7174
def traverse[G[_]: Applicative, A, B](sa: Set[A])(f: A => G[B]): G[Set[B]] = {
7275
val G = Applicative[G]
7376
sa.foldLeft(G.pure(Set.empty[B])) { (buf, a) =>

core/src/main/scala/cats/data/NonEmptyList.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ private[data] sealed abstract class NonEmptyListInstances extends NonEmptyListIn
472472
override def foldRight[A, B](fa: NonEmptyList[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
473473
fa.foldRight(lb)(f)
474474

475+
override def foldMap[A, B](fa: NonEmptyList[A])(f: A => B)(implicit B: Monoid[B]): B =
476+
B.combineAll(fa.toList.iterator.map(f))
477+
475478
def tailRecM[A, B](a: A)(f: A => NonEmptyList[Either[A, B]]): NonEmptyList[B] = {
476479
val buf = new ListBuffer[B]
477480
@tailrec def go(v: NonEmptyList[Either[A, B]]): Unit = v.head match {

core/src/main/scala/cats/data/NonEmptyVector.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ private[data] sealed abstract class NonEmptyVectorInstances {
290290
override def foldRight[A, B](fa: NonEmptyVector[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
291291
fa.foldRight(lb)(f)
292292

293+
override def foldMap[A, B](fa: NonEmptyVector[A])(f: A => B)(implicit B: Monoid[B]): B =
294+
B.combineAll(fa.toVector.iterator.map(f))
295+
293296
override def nonEmptyPartition[A, B, C](fa: NonEmptyVector[A])(f: (A) => Either[B, C]): Ior[NonEmptyList[B], NonEmptyList[C]] = {
294297
import cats.syntax.either._
295298
import cats.syntax.reducible._

core/src/main/scala/cats/instances/list.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
6565
Eval.defer(loop(fa))
6666
}
6767

68+
override def foldMap[A, B](fa: List[A])(f: A => B)(implicit B: Monoid[B]): B =
69+
B.combineAll(fa.iterator.map(f))
70+
6871
def traverse[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
6972
foldRight[A, G[List[B]]](fa, Always(G.pure(List.empty))){ (a, lglb) =>
7073
G.map2Eval(f(a), lglb)(_ :: _)

core/src/main/scala/cats/instances/queue.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cats
22
package instances
33

44
import cats.syntax.show._
5-
65
import scala.annotation.tailrec
76
import scala.collection.immutable.Queue
87
import scala.util.Try
@@ -75,6 +74,9 @@ trait QueueInstances extends cats.kernel.instances.QueueInstances {
7574
Eval.defer(loop(fa))
7675
}
7776

77+
override def foldMap[A, B](fa: Queue[A])(f: A => B)(implicit B: Monoid[B]): B =
78+
B.combineAll(fa.iterator.map(f))
79+
7880
def traverse[G[_], A, B](fa: Queue[A])(f: A => G[B])(implicit G: Applicative[G]): G[Queue[B]] =
7981
foldRight[A, G[Queue[B]]](fa, Always(G.pure(Queue.empty))){ (a, lglb) =>
8082
G.map2Eval(f(a), lglb)(_ +: _)

core/src/main/scala/cats/instances/sortedSet.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ trait SortedSetInstances extends SortedSetInstances1 {
1919
def foldRight[A, B](fa: SortedSet[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
2020
Foldable.iterateRight(fa, lb)(f)
2121

22+
override def foldMap[A, B](fa: SortedSet[A])(f: A => B)(implicit B: Monoid[B]): B =
23+
B.combineAll(fa.iterator.map(f))
24+
2225
override def get[A](fa: SortedSet[A])(idx: Long): Option[A] = {
2326
@tailrec
2427
def go(idx: Int, it: Iterator[A]): Option[A] = {

core/src/main/scala/cats/instances/stream.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
4242
if (s.isEmpty) lb else f(s.head, Eval.defer(foldRight(s.tail, lb)(f)))
4343
}
4444

45+
override def foldMap[A, B](fa: Stream[A])(f: A => B)(implicit B: Monoid[B]): B =
46+
B.combineAll(fa.iterator.map(f))
47+
4548
def traverse[G[_], A, B](fa: Stream[A])(f: A => G[B])(implicit G: Applicative[G]): G[Stream[B]] = {
4649
// We use foldRight to avoid possible stack overflows. Since
4750
// we don't want to return a Eval[_] instance, we call .value

core/src/main/scala/cats/instances/vector.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {
4141
Eval.defer(loop(0))
4242
}
4343

44+
override def foldMap[A, B](fa: Vector[A])(f: A => B)(implicit B: Monoid[B]): B =
45+
B.combineAll(fa.iterator.map(f))
46+
4447
def tailRecM[A, B](a: A)(fn: A => Vector[Either[A, B]]): Vector[B] = {
4548
val buf = Vector.newBuilder[B]
4649
var state = List(fn(a).iterator)

0 commit comments

Comments
 (0)