Skip to content

Commit 478e1a4

Browse files
authored
Merge pull request #4662 from m50d/unorderedfoldmapm
Add `unorderedFoldMapA` method
2 parents 0bb930f + 2fd1efd commit 478e1a4

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

core/src/main/scala/cats/UnorderedFoldable.scala

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@ trait UnorderedFoldable[F[_]] extends Serializable {
3535
def unorderedFold[A: CommutativeMonoid](fa: F[A]): A =
3636
unorderedFoldMap(fa)(identity)
3737

38+
/**
39+
* Fold in a [[CommutativeApplicative]] context by mapping the `A` values to `G[B]`. combining
40+
* the `B` values using the given `CommutativeMonoid[B]` instance.
41+
*
42+
* {{{
43+
* scala> import cats.UnorderedFoldable
44+
* scala> import cats.syntax.all._
45+
* scala> val evenNumbers = Set(2,4,6,8,10)
46+
* scala> val evenOpt: Int => Option[Int] =
47+
* | i => if (i % 2 == 0) Some(i) else None
48+
* scala> UnorderedFoldable[Set].unorderedFoldMapA(evenNumbers)(evenOpt)
49+
* res0: Option[Int] = Some(30)
50+
* scala> UnorderedFoldable[Set].unorderedFoldMapA(evenNumbers + 11)(evenOpt)
51+
* res1: Option[Int] = None
52+
* }}}
53+
*/
54+
def unorderedFoldMapA[G[_], A, B](fa: F[A])(
55+
f: A => G[B]
56+
)(implicit G: CommutativeApplicative[G], B: CommutativeMonoid[B]): G[B] =
57+
unorderedFoldMap(fa)(f)(CommutativeApplicative.commutativeMonoidFor)
58+
3859
/**
3960
* Tests if `fa` contains `v` using the `Eq` instance for `A`
4061
*/
@@ -170,6 +191,10 @@ object UnorderedFoldable
170191
def unorderedFoldMap[B](f: A => B)(implicit ev$1: CommutativeMonoid[B]): B =
171192
typeClassInstance.unorderedFoldMap[A, B](self)(f)
172193
def unorderedFold(implicit ev$1: CommutativeMonoid[A]): A = typeClassInstance.unorderedFold[A](self)
194+
def unorderedFoldMapA[G[_], B](
195+
f: A => G[B]
196+
)(implicit ev$1: CommutativeApplicative[G], ev$2: CommutativeMonoid[B]): G[B] =
197+
typeClassInstance.unorderedFoldMapA[G, A, B](self)(f)
173198
def isEmpty: Boolean = typeClassInstance.isEmpty[A](self)
174199
def nonEmpty: Boolean = typeClassInstance.nonEmpty[A](self)
175200
def exists(p: A => Boolean): Boolean = typeClassInstance.exists[A](self)(p)
@@ -189,5 +214,4 @@ object UnorderedFoldable
189214
}
190215
@deprecated("Use cats.syntax object imports", "2.2.0")
191216
object nonInheritedOps extends ToUnorderedFoldableOps
192-
193217
}

laws/src/main/scala/cats/laws/UnorderedFoldableLaws.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ trait UnorderedFoldableLaws[F[_]] {
3030
def unorderedFoldConsistentWithUnorderedFoldMap[A: CommutativeMonoid](fa: F[A]): IsEq[A] =
3131
F.unorderedFoldMap(fa)(identity) <-> F.unorderedFold(fa)
3232

33+
def unorderedFoldMapAIdentity[A, B: CommutativeMonoid](fa: F[A], f: A => B): IsEq[B] =
34+
F.unorderedFoldMapA[Id, A, B](fa)(f) <-> F.unorderedFoldMap(fa)(f)
35+
3336
def forallConsistentWithExists[A](fa: F[A], p: A => Boolean): Boolean =
3437
if (F.forall(fa)(p)) {
3538
val negationExists = F.exists(fa)(a => !p(a))

laws/src/main/scala/cats/laws/discipline/UnorderedFoldableTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ trait UnorderedFoldableTests[F[_]] extends Laws {
4545
name = "unorderedFoldable",
4646
parent = None,
4747
"unorderedFold consistent with unorderedFoldMap" -> forAll(laws.unorderedFoldConsistentWithUnorderedFoldMap[A] _),
48+
"unorderedFoldMapA identity" -> forAll(laws.unorderedFoldMapAIdentity[A, B] _),
4849
"forall consistent with exists" -> forAll(laws.forallConsistentWithExists[A] _),
4950
"forall true if empty" -> forAll(laws.forallEmpty[A] _),
5051
"nonEmpty reference" -> forAll(laws.nonEmptyRef[A] _),

0 commit comments

Comments
 (0)