Skip to content

Commit

Permalink
Merge pull request #4662 from m50d/unorderedfoldmapm
Browse files Browse the repository at this point in the history
Add `unorderedFoldMapA` method
  • Loading branch information
satorg authored Oct 10, 2024
2 parents 0bb930f + 2fd1efd commit 478e1a4
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 1 deletion.
26 changes: 25 additions & 1 deletion core/src/main/scala/cats/UnorderedFoldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,27 @@ trait UnorderedFoldable[F[_]] extends Serializable {
def unorderedFold[A: CommutativeMonoid](fa: F[A]): A =
unorderedFoldMap(fa)(identity)

/**
* Fold in a [[CommutativeApplicative]] context by mapping the `A` values to `G[B]`. combining
* the `B` values using the given `CommutativeMonoid[B]` instance.
*
* {{{
* scala> import cats.UnorderedFoldable
* scala> import cats.syntax.all._
* scala> val evenNumbers = Set(2,4,6,8,10)
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
* scala> UnorderedFoldable[Set].unorderedFoldMapA(evenNumbers)(evenOpt)
* res0: Option[Int] = Some(30)
* scala> UnorderedFoldable[Set].unorderedFoldMapA(evenNumbers + 11)(evenOpt)
* res1: Option[Int] = None
* }}}
*/
def unorderedFoldMapA[G[_], A, B](fa: F[A])(
f: A => G[B]
)(implicit G: CommutativeApplicative[G], B: CommutativeMonoid[B]): G[B] =
unorderedFoldMap(fa)(f)(CommutativeApplicative.commutativeMonoidFor)

/**
* Tests if `fa` contains `v` using the `Eq` instance for `A`
*/
Expand Down Expand Up @@ -170,6 +191,10 @@ object UnorderedFoldable
def unorderedFoldMap[B](f: A => B)(implicit ev$1: CommutativeMonoid[B]): B =
typeClassInstance.unorderedFoldMap[A, B](self)(f)
def unorderedFold(implicit ev$1: CommutativeMonoid[A]): A = typeClassInstance.unorderedFold[A](self)
def unorderedFoldMapA[G[_], B](
f: A => G[B]
)(implicit ev$1: CommutativeApplicative[G], ev$2: CommutativeMonoid[B]): G[B] =
typeClassInstance.unorderedFoldMapA[G, A, B](self)(f)
def isEmpty: Boolean = typeClassInstance.isEmpty[A](self)
def nonEmpty: Boolean = typeClassInstance.nonEmpty[A](self)
def exists(p: A => Boolean): Boolean = typeClassInstance.exists[A](self)(p)
Expand All @@ -189,5 +214,4 @@ object UnorderedFoldable
}
@deprecated("Use cats.syntax object imports", "2.2.0")
object nonInheritedOps extends ToUnorderedFoldableOps

}
3 changes: 3 additions & 0 deletions laws/src/main/scala/cats/laws/UnorderedFoldableLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ trait UnorderedFoldableLaws[F[_]] {
def unorderedFoldConsistentWithUnorderedFoldMap[A: CommutativeMonoid](fa: F[A]): IsEq[A] =
F.unorderedFoldMap(fa)(identity) <-> F.unorderedFold(fa)

def unorderedFoldMapAIdentity[A, B: CommutativeMonoid](fa: F[A], f: A => B): IsEq[B] =
F.unorderedFoldMapA[Id, A, B](fa)(f) <-> F.unorderedFoldMap(fa)(f)

def forallConsistentWithExists[A](fa: F[A], p: A => Boolean): Boolean =
if (F.forall(fa)(p)) {
val negationExists = F.exists(fa)(a => !p(a))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ trait UnorderedFoldableTests[F[_]] extends Laws {
name = "unorderedFoldable",
parent = None,
"unorderedFold consistent with unorderedFoldMap" -> forAll(laws.unorderedFoldConsistentWithUnorderedFoldMap[A] _),
"unorderedFoldMapA identity" -> forAll(laws.unorderedFoldMapAIdentity[A, B] _),
"forall consistent with exists" -> forAll(laws.forallConsistentWithExists[A] _),
"forall true if empty" -> forAll(laws.forallEmpty[A] _),
"nonEmpty reference" -> forAll(laws.nonEmptyRef[A] _),
Expand Down

0 comments on commit 478e1a4

Please sign in to comment.