Skip to content

Commit

Permalink
Expand foldA, reduceA, and reduceMapA API docs
Browse files Browse the repository at this point in the history
  • Loading branch information
travisbrown committed Dec 10, 2019
1 parent faa1f92 commit bc6e5d9
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 14 deletions.
28 changes: 20 additions & 8 deletions core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ import Foldable.sentinel
)

/**
* Fold implemented using the given Monoid[A] instance.
* Fold implemented using the given `Monoid[A]` instance.
*/
def fold[A](fa: F[A])(implicit A: Monoid[A]): A =
A.combineAll(toIterable(fa))
Expand Down Expand Up @@ -397,8 +397,7 @@ import Foldable.sentinel
/**
* Fold implemented using the given `Applicative[G]` and `Monoid[A]` instance.
*
* This method is identical to fold, except that we use `Applicative[G]` and `Monoid[A]`
* to combine a's inside an applicative G.
* This method is similar to [[fold]], but may short-circuit.
*
* For example:
*
Expand All @@ -409,7 +408,7 @@ import Foldable.sentinel
* res0: Either[String, Int] = Right(3)
* }}}
*
* `noop` usage description [[https://github.com/typelevel/simulacrum/issues/162 here]]
* See [[https://github.com/typelevel/simulacrum/issues/162 this issue]] for an explanation of `@noop` usage.
*/
@noop def foldA[G[_], A](fga: F[G[A]])(implicit G: Applicative[G], A: Monoid[A]): G[A] =
foldMapA(fga)(identity)
Expand Down Expand Up @@ -440,7 +439,7 @@ import Foldable.sentinel
* Monadic folding on `F` by mapping `A` values to `G[B]`, combining the `B`
* values using the given `Monoid[B]` instance.
*
* Similar to [[foldM]], but using a `Monoid[B]`.
* Similar to [[foldM]], but using a `Monoid[B]`. Will typically be more efficient than [[foldMapA]].
*
* {{{
* scala> import cats.Foldable
Expand All @@ -458,9 +457,22 @@ import Foldable.sentinel
foldM(fa, B.empty)((b, a) => G.map(f(a))(B.combine(b, _)))

/**
* Equivalent to foldMapM.
* The difference is that foldMapA only requires G to be an Applicative
* rather than a Monad. It is also slower due to use of Eval.
* Fold in an [[Applicative]] context by mapping the `A` values to `G[B]`. combining
* the `B` values using the given `Monoid[B]` instance.
*
* Similar to [[foldMapM]], but will typically be less efficient.
*
* {{{
* scala> import cats.Foldable
* scala> import cats.implicits._
* scala> val evenNumbers = List(2,4,6,8,10)
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
* scala> Foldable[List].foldMapA(evenNumbers)(evenOpt)
* res0: Option[Int] = Some(30)
* scala> Foldable[List].foldMapA(evenNumbers :+ 11)(evenOpt)
* res1: Option[Int] = None
* }}}
*/
def foldMapA[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G], B: Monoid[B]): G[B] =
foldRight(fa, Eval.now(G.pure(B.empty)))((a, egb) => G.map2Eval(f(a), egb)(B.combine)).value
Expand Down
32 changes: 26 additions & 6 deletions core/src/main/scala/cats/Reducible.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import simulacrum.{noop, typeclass}
def reduceLeftTo[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): B

/**
* Monadic variant of [[reduceLeftTo]]
* Monadic variant of [[reduceLeftTo]].
*/
def reduceLeftM[G[_], A, B](fa: F[A])(f: A => G[B])(g: (B, A) => G[B])(implicit G: FlatMap[G]): G[B] =
reduceLeftTo(fa)(f)((gb, a) => G.flatMap(gb)(g(_, a)))
Expand All @@ -86,23 +86,43 @@ import simulacrum.{noop, typeclass}
* Reduce a `F[G[A]]` value using `Applicative[G]` and `Semigroup[A]`, a universal
* semigroup for `G[_]`.
*
* `noop` usage description [[https://github.com/typelevel/simulacrum/issues/162 here]]
* This method is similar to [[reduce]], but may short-circuit.
*
* See [[https://github.com/typelevel/simulacrum/issues/162 this issue]] for an explanation of `@noop` usage.
*/
@noop def reduceA[G[_], A](fga: F[G[A]])(implicit G: Apply[G], A: Semigroup[A]): G[A] =
reduceMapA(fga)(identity)

/**
* Apply `f` to each `a` of `fa` and combine the result into Apply[G] using the
* given `Semigroup[B]`.
* Reduce in an [[Apply]] context by mapping the `A` values to `G[B]`. combining
* the `B` values using the given `Semigroup[B]` instance.
*
* Similar to [[reduceMapM]], but may be less efficient.
*
* {{{
* scala> import cats.Reducible
* scala> import cats.data.NonEmptyList
* scala> import cats.implicits._
* scala> val evenOpt: Int => Option[Int] =
* | i => if (i % 2 == 0) Some(i) else None
* scala> val allEven = NonEmptyList.of(2,4,6,8,10)
* allEven: cats.data.NonEmptyList[Int] = NonEmptyList(2, 4, 6, 8, 10)
* scala> val notAllEven = allEven ++ List(11)
* notAllEven: cats.data.NonEmptyList[Int] = NonEmptyList(2, 4, 6, 8, 10, 11)
* scala> Reducible[NonEmptyList].reduceMapA(allEven)(evenOpt)
* res0: Option[Int] = Some(30)
* scala> Reducible[NonEmptyList].reduceMapA(notAllEven)(evenOpt)
* res1: Option[Int] = None
* }}}
*/
def reduceMapA[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Apply[G], B: Semigroup[B]): G[B] =
reduceRightTo(fa)(f)((a, egb) => G.map2Eval(f(a), egb)(B.combine)).value

/**
* Monadic reducing by mapping the `A` values to `G[B]`. combining
* Reduce in an [[FlatMap]] context by mapping the `A` values to `G[B]`. combining
* the `B` values using the given `Semigroup[B]` instance.
*
* Similar to [[reduceLeftM]], but using a `Semigroup[B]`.
* Similar to [[reduceLeftM]], but using a `Semigroup[B]`. May be more efficient than [[reduceMapA]].
*
* {{{
* scala> import cats.Reducible
Expand Down

0 comments on commit bc6e5d9

Please sign in to comment.