cats.Foldable.scala Maven / Gradle / Ivy
The newest version!
package cats
import scala.collection.mutable
import cats.kernel.CommutativeMonoid
import simulacrum.{noop, typeclass}
import Foldable.sentinel
/**
* Data structures that can be folded to a summary value.
*
* In the case of a collection (such as `List` or `Vector`), these
* methods will fold together (combine) the values contained in the
* collection to produce a single result. Most collection types have
* `foldLeft` methods, which will usually be used by the associated
* `Foldable[_]` instance.
*
* Instances of Foldable should be ordered collections to allow for consistent folding.
* Use the `UnorderedFoldable` type class if you want to fold over unordered collections.
*
* Foldable[F] is implemented in terms of two basic methods:
*
* - `foldLeft(fa, b)(f)` eagerly folds `fa` from left-to-right.
* - `foldRight(fa, b)(f)` lazily folds `fa` from right-to-left.
*
* Beyond these it provides many other useful methods related to
* folding over F[A] values.
*
* See: [[http://www.cs.nott.ac.uk/~pszgmh/fold.pdf A tutorial on the universality and expressiveness of fold]]
*/
@typeclass trait Foldable[F[_]] extends UnorderedFoldable[F] { self =>
/**
* Left associative fold on 'F' using the function 'f'.
*
* Example:
* {{{
* scala> import cats.Foldable, cats.implicits._
* scala> val fa = Option(1)
*
* Folding by addition to zero:
* scala> Foldable[Option].foldLeft(fa, Option(0))((a, n) => a.map(_ + n))
* res0: Option[Int] = Some(1)
* }}}
*
* With syntax extensions, `foldLeft` can be used like:
* {{{
* Folding `Option` with addition from zero:
* scala> fa.foldLeft(Option(0))((a, n) => a.map(_ + n))
* res1: Option[Int] = Some(1)
*
* There's also an alias `foldl` which is equivalent:
* scala> fa.foldl(Option(0))((a, n) => a.map(_ + n))
* res2: Option[Int] = Some(1)
* }}}
*/
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B
/**
* Right associative lazy fold on `F` using the folding function 'f'.
*
* This method evaluates `lb` lazily (in some cases it will not be
* needed), and returns a lazy value. We are using `(A, Eval[B]) =>
* Eval[B]` to support laziness in a stack-safe way. Chained
* computation should be performed via .map and .flatMap.
*
* For more detailed information about how this method works see the
* documentation for `Eval[_]`.
*
* Example:
* {{{
* scala> import cats.Foldable, cats.Eval, cats.implicits._
* scala> val fa = Option(1)
*
* Folding by addition to zero:
* scala> val folded1 = Foldable[Option].foldRight(fa, Eval.now(0))((n, a) => a.map(_ + n))
* Since `foldRight` yields a lazy computation, we need to force it to inspect the result:
* scala> folded1.value
* res0: Int = 1
*
* With syntax extensions, we can write the same thing like this:
* scala> val folded2 = fa.foldRight(Eval.now(0))((n, a) => a.map(_ + n))
* scala> folded2.value
* res1: Int = 1
*
* Unfortunately, since `foldRight` is defined on many collections - this
* extension clashes with the operation defined in `Foldable`.
*
* To get past this and make sure you're getting the lazy `foldRight` defined
* in `Foldable`, there's an alias `foldr`:
* scala> val folded3 = fa.foldr(Eval.now(0))((n, a) => a.map(_ + n))
* scala> folded3.value
* res1: Int = 1
* }}}
*/
def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B]
def foldRightDefer[G[_]: Defer, A, B](fa: F[A], gb: G[B])(fn: (A, G[B]) => G[B]): G[B] =
Defer[G].defer(
this.foldLeft(fa, (z: G[B]) => z) { (acc, elem) => z =>
Defer[G].defer(acc(fn(elem, z)))
}(gb)
)
def reduceLeftToOption[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): Option[B] =
foldLeft(fa, Option.empty[B]) {
case (Some(b), a) => Some(g(b, a))
case (None, a) => Some(f(a))
}
def reduceRightToOption[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] =
foldRight(fa, Now(Option.empty[B])) { (a, lb) =>
lb.flatMap {
case Some(b) => g(a, Now(b)).map(Some(_))
case None => Later(Some(f(a)))
}
}
/**
* Reduce the elements of this structure down to a single value by applying
* the provided aggregation function in a left-associative manner.
*
* @return `None` if the structure is empty, otherwise the result of combining
* the cumulative left-associative result of the `f` operation over all of the
* elements.
*
* @see [[reduceRightOption]] for a right-associative alternative.
*
* @see [[Reducible#reduceLeft]] for a version that doesn't need to return an
* `Option` for structures that are guaranteed to be non-empty.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val l = List(6, 3, 2)
* This is equivalent to (6 - 3) - 2
* scala> Foldable[List].reduceLeftOption(l)(_ - _)
* res0: Option[Int] = Some(1)
*
* scala> Foldable[List].reduceLeftOption(List.empty[Int])(_ - _)
* res1: Option[Int] = None
* }}}
*/
def reduceLeftOption[A](fa: F[A])(f: (A, A) => A): Option[A] =
reduceLeftToOption(fa)(identity)(f)
/**
* Reduce the elements of this structure down to a single value by applying
* the provided aggregation function in a right-associative manner.
*
* @return `None` if the structure is empty, otherwise the result of combining
* the cumulative right-associative result of the `f` operation over the
* `A` elements.
*
* @see [[reduceLeftOption]] for a left-associative alternative
*
* @see [[Reducible#reduceRight]] for a version that doesn't need to return an
* `Option` for structures that are guaranteed to be non-empty.
*
* Example:
* {{{
* scala> import cats.implicits._
* scala> val l = List(6, 3, 2)
* This is eqivalent to 6 - (3 - 2)
* scala> Foldable[List].reduceRightOption(l)((current, rest) => rest.map(current - _)).value
* res0: Option[Int] = Some(5)
*
* scala> Foldable[List].reduceRightOption(List.empty[Int])((current, rest) => rest.map(current - _)).value
* res1: Option[Int] = None
* }}}
*/
def reduceRightOption[A](fa: F[A])(f: (A, Eval[A]) => Eval[A]): Eval[Option[A]] =
reduceRightToOption(fa)(identity)(f)
/**
* Find the minimum `A` item in this structure according to the `Order[A]`.
*
* @return `None` if the structure is empty, otherwise the minimum element
* wrapped in a `Some`.
*
* @see [[Reducible#minimum]] for a version that doesn't need to return an
* `Option` for structures that are guaranteed to be non-empty.
*
* @see [[maximumOption]] for maximum instead of minimum.
*/
def minimumOption[A](fa: F[A])(implicit A: Order[A]): Option[A] =
reduceLeftOption(fa)(A.min)
/**
* Find the maximum `A` item in this structure according to the `Order[A]`.
*
* @return `None` if the structure is empty, otherwise the maximum element
* wrapped in a `Some`.
*
* @see [[Reducible#maximum]] for a version that doesn't need to return an
* `Option` for structures that are guaranteed to be non-empty.
*
* @see [[minimumOption]] for minimum instead of maximum.
*/
def maximumOption[A](fa: F[A])(implicit A: Order[A]): Option[A] =
reduceLeftOption(fa)(A.max)
/**
* Find the minimum `A` item in this structure according to an `Order.by(f)`.
*
* @return `None` if the structure is empty, otherwise the minimum element
* wrapped in a `Some`.
*
* @see [[Reducible#minimumBy]] for a version that doesn't need to return an
* `Option` for structures that are guaranteed to be non-empty.
*
* @see [[maximumByOption]] for maximum instead of minimum.
*/
def minimumByOption[A, B: Order](fa: F[A])(f: A => B): Option[A] =
minimumOption(fa)(Order.by(f))
/**
* Find the maximum `A` item in this structure according to an `Order.by(f)`.
*
* @return `None` if the structure is empty, otherwise the maximum element
* wrapped in a `Some`.
*
* @see [[Reducible#maximumBy]] for a version that doesn't need to return an
* `Option` for structures that are guaranteed to be non-empty.
*
* @see [[minimumByOption]] for minimum instead of maximum.
*/
def maximumByOption[A, B: Order](fa: F[A])(f: A => B): Option[A] =
maximumOption(fa)(Order.by(f))
/**
* Get the element at the index of the `Foldable`.
*/
def get[A](fa: F[A])(idx: Long): Option[A] =
if (idx < 0L) None
else
foldM[Either[A, *], A, Long](fa, 0L) { (i, a) =>
if (i == idx) Left(a) else Right(i + 1L)
} match {
case Left(a) => Some(a)
case Right(_) => None
}
def collectFirst[A, B](fa: F[A])(pf: PartialFunction[A, B]): Option[B] =
foldRight(fa, Eval.now(Option.empty[B])) { (a, lb) =>
// trick from TraversableOnce, used to avoid calling both isDefined and apply (or calling lift)
val x = pf.applyOrElse(a, sentinel)
if (x.asInstanceOf[AnyRef] ne sentinel) Eval.now(Some(x.asInstanceOf[B]))
else lb
}.value
/**
* Like `collectFirst` from `scala.collection.Traversable` but takes `A => Option[B]`
* instead of `PartialFunction`s.
* {{{
* scala> import cats.implicits._
* scala> val keys = List(1, 2, 4, 5)
* scala> val map = Map(4 -> "Four", 5 -> "Five")
* scala> keys.collectFirstSome(map.get)
* res0: Option[String] = Some(Four)
* scala> val map2 = Map(6 -> "Six", 7 -> "Seven")
* scala> keys.collectFirstSome(map2.get)
* res1: Option[String] = None
* }}}
*/
def collectFirstSome[A, B](fa: F[A])(f: A => Option[B]): Option[B] =
foldRight(fa, Eval.now(Option.empty[B])) { (a, lb) =>
val ob = f(a)
if (ob.isDefined) Eval.now(ob) else lb
}.value
/**
* Monadic version of `collectFirstSome`.
*
* If there are no elements, the result is `None`. `collectFirstSomeM` short-circuits,
* i.e. once a Some element is found, no further effects are produced.
*
* For example:
* {{{
* scala> import cats.implicits._
* scala> def parseInt(s: String): Either[String, Int] = Either.catchOnly[NumberFormatException](s.toInt).leftMap(_.getMessage)
* scala> val keys1 = List("1", "2", "4", "5")
* scala> val map1 = Map(4 -> "Four", 5 -> "Five")
* scala> Foldable[List].collectFirstSomeM(keys1)(parseInt(_) map map1.get)
* res0: scala.util.Either[String,Option[String]] = Right(Some(Four))
*
* scala> val map2 = Map(6 -> "Six", 7 -> "Seven")
* scala> Foldable[List].collectFirstSomeM(keys1)(parseInt(_) map map2.get)
* res1: scala.util.Either[String,Option[String]] = Right(None)
*
* scala> val keys2 = List("1", "x", "4", "5")
* scala> Foldable[List].collectFirstSomeM(keys2)(parseInt(_) map map1.get)
* res2: scala.util.Either[String,Option[String]] = Left(For input string: "x")
*
* scala> val keys3 = List("1", "2", "4", "x")
* scala> Foldable[List].collectFirstSomeM(keys3)(parseInt(_) map map1.get)
* res3: scala.util.Either[String,Option[String]] = Right(Some(Four))
* }}}
*/
@noop
def collectFirstSomeM[G[_], A, B](fa: F[A])(f: A => G[Option[B]])(implicit G: Monad[G]): G[Option[B]] =
G.tailRecM(Foldable.Source.fromFoldable(fa)(self))(_.uncons match {
case Some((a, src)) =>
G.map(f(a)) {
case None => Left(src.value)
case s => Right(s)
}
case None => G.pure(Right(None))
})
/**
* Tear down a subset of this structure using a `PartialFunction`.
*{{{
* scala> import cats.implicits._
* scala> val xs = List(1, 2, 3, 4)
* scala> Foldable[List].collectFold(xs) { case n if n % 2 == 0 => n }
* res0: Int = 6
*}}}
*/
@noop
def collectFold[A, B](fa: F[A])(f: PartialFunction[A, B])(implicit B: Monoid[B]): B =
foldLeft(fa, B.empty)((acc, a) => B.combine(acc, f.applyOrElse(a, (_: A) => B.empty)))
/**
* Tear down a subset of this structure using a `A => Option[M]`.
*{{{
* scala> import cats.implicits._
* scala> val xs = List(1, 2, 3, 4)
* scala> def f(n: Int): Option[Int] = if (n % 2 == 0) Some(n) else None
* scala> Foldable[List].collectFoldSome(xs)(f)
* res0: Int = 6
*}}}
*/
def collectFoldSome[A, B](fa: F[A])(f: A => Option[B])(implicit B: Monoid[B]): B =
foldLeft(fa, B.empty)(
(acc, a) =>
f(a) match {
case Some(x) => B.combine(acc, x)
case None => acc
}
)
/**
* Fold implemented using the given `Monoid[A]` instance.
*/
def fold[A](fa: F[A])(implicit A: Monoid[A]): A =
A.combineAll(toIterable(fa))
/**
* Alias for [[fold]].
*/
def combineAll[A: Monoid](fa: F[A]): A = fold(fa)
def combineAllOption[A](fa: F[A])(implicit ev: Semigroup[A]): Option[A] =
if (isEmpty(fa)) None else ev.combineAllOption(toIterable(fa))
/**
* Convert F[A] to an Iterable[A].
*
* This method may be overridden for the sake of performance, but implementers should take care
* not to force a full materialization of the collection.
*/
def toIterable[A](fa: F[A]): Iterable[A] =
cats.compat.FoldableCompat.toIterable(fa)(self)
/**
* Fold implemented by mapping `A` values into `B` and then
* combining them using the given `Monoid[B]` instance.
*/
def foldMap[A, B](fa: F[A])(f: A => B)(implicit B: Monoid[B]): B =
foldLeft(fa, B.empty)((b, a) => B.combine(b, f(a)))
/**
* Perform a stack-safe monadic left fold from the source context `F`
* into the target monad `G`.
*
* This method can express short-circuiting semantics. Even when
* `fa` is an infinite structure, this method can potentially
* terminate if the `foldRight` implementation for `F` and the
* `tailRecM` implementation for `G` are sufficiently lazy.
*
* Instances for concrete structures (e.g. `List`) will often
* have a more efficient implementation than the default one
* in terms of `foldRight`.
*/
def foldM[G[_], A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] = {
val src = Foldable.Source.fromFoldable(fa)(self)
G.tailRecM((z, src)) {
case (b, src) =>
src.uncons match {
case Some((a, src)) => G.map(f(b, a))(b => Left((b, src.value)))
case None => G.pure(Right(b))
}
}
}
/**
* Fold implemented using the given `Applicative[G]` and `Monoid[A]` instance.
*
* This method is similar to [[fold]], but may short-circuit.
*
* For example:
*
* {{{
* scala> import cats.implicits._
* scala> val F = Foldable[List]
* scala> F.foldA(List(Either.right[String, Int](1), Either.right[String, Int](2)))
* res0: Either[String, Int] = Right(3)
* }}}
*
* 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)
/**
* Fold implemented by mapping `A` values into `B` in a context `G` and then
* combining them using the `MonoidK[G]` instance.
*
* {{{
* scala> import cats._, cats.implicits._
* scala> val f: Int => Endo[String] = i => (s => s + i)
* scala> val x: Endo[String] = Foldable[List].foldMapK(List(1, 2, 3))(f)
* scala> val a = x("foo")
* a: String = "foo321"
* }}}
* */
@noop
def foldMapK[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: MonoidK[G]): G[B] =
foldMap(fa)(f)(G.algebra)
/**
* Alias for [[foldM]].
*/
final def foldLeftM[G[_], A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] =
foldM(fa, z)(f)
/**
* 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]`. Will typically be more efficient than [[foldMapA]].
*
* {{{
* 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].foldMapM(evenNumbers)(evenOpt)
* res0: Option[Int] = Some(30)
* scala> Foldable[List].foldMapM(evenNumbers :+ 11)(evenOpt)
* res1: Option[Int] = None
* }}}
*/
def foldMapM[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Monad[G], B: Monoid[B]): G[B] =
foldM(fa, B.empty)((b, a) => G.map(f(a))(B.combine(b, _)))
/**
* 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
/**
* Traverse `F[A]` using `Applicative[G]`.
*
* `A` values will be mapped into `G[B]` and combined using
* `Applicative#map2`.
*
* For example:
*
* {{{
* scala> import cats.implicits._
* scala> def parseInt(s: String): Option[Int] = Either.catchOnly[NumberFormatException](s.toInt).toOption
* scala> val F = Foldable[List]
* scala> F.traverse_(List("333", "444"))(parseInt)
* res0: Option[Unit] = Some(())
* scala> F.traverse_(List("333", "zzz"))(parseInt)
* res1: Option[Unit] = None
* }}}
*
* This method is primarily useful when `G[_]` represents an action
* or effect, and the specific `A` aspect of `G[A]` is not otherwise
* needed.
*/
def traverse_[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[Unit] =
foldRight(fa, Always(G.pure(()))) { (a, acc) =>
G.map2Eval(f(a), acc) { (_, _) =>
()
}
}.value
/**
* Sequence `F[G[A]]` using `Applicative[G]`.
*
* This is similar to `traverse_` except it operates on `F[G[A]]`
* values, so no additional functions are needed.
*
* For example:
*
* {{{
* scala> import cats.implicits._
* scala> val F = Foldable[List]
* scala> F.sequence_(List(Option(1), Option(2), Option(3)))
* res0: Option[Unit] = Some(())
* scala> F.sequence_(List(Option(1), None, Option(3)))
* res1: Option[Unit] = None
* }}}
*/
def sequence_[G[_]: Applicative, A](fga: F[G[A]]): G[Unit] =
traverse_(fga)(identity)
/**
* Fold implemented using the given `MonoidK[G]` instance.
*
* This method is identical to fold, except that we use the universal monoid (`MonoidK[G]`)
* to get a `Monoid[G[A]]` instance.
*
* For example:
*
* {{{
* scala> import cats.implicits._
* scala> val F = Foldable[List]
* scala> F.foldK(List(1 :: 2 :: Nil, 3 :: 4 :: 5 :: Nil))
* res0: List[Int] = List(1, 2, 3, 4, 5)
* }}}
*/
def foldK[G[_], A](fga: F[G[A]])(implicit G: MonoidK[G]): G[A] =
fold(fga)(G.algebra)
/**
* Find the first element matching the predicate, if one exists.
*/
def find[A](fa: F[A])(f: A => Boolean): Option[A] =
foldRight(fa, Now(Option.empty[A])) { (a, lb) =>
if (f(a)) Now(Some(a)) else lb
}.value
/**
* Find the first element matching the effectful predicate, if one exists.
*
* If there are no elements, the result is `None`. `findM` short-circuits,
* i.e. once an element is found, no further effects are produced.
*
* For example:
* {{{
* scala> import cats.implicits._
* scala> val list = List(1,2,3,4)
* scala> Foldable[List].findM(list)(n => (n >= 2).asRight[String])
* res0: Either[String,Option[Int]] = Right(Some(2))
*
* scala> Foldable[List].findM(list)(n => (n > 4).asRight[String])
* res1: Either[String,Option[Int]] = Right(None)
*
* scala> Foldable[List].findM(list)(n => Either.cond(n < 3, n >= 2, "error"))
* res2: Either[String,Option[Int]] = Right(Some(2))
*
* scala> Foldable[List].findM(list)(n => Either.cond(n < 3, false, "error"))
* res3: Either[String,Option[Int]] = Left(error)
* }}}
*/
@noop
def findM[G[_], A](fa: F[A])(p: A => G[Boolean])(implicit G: Monad[G]): G[Option[A]] =
G.tailRecM(Foldable.Source.fromFoldable(fa)(self))(_.uncons match {
case Some((a, src)) => G.map(p(a))(if (_) Right(Some(a)) else Left(src.value))
case None => G.pure(Right(None))
})
/**
* Check whether at least one element satisfies the predicate.
*
* If there are no elements, the result is `false`.
*/
override def exists[A](fa: F[A])(p: A => Boolean): Boolean =
foldRight(fa, Eval.False) { (a, lb) =>
if (p(a)) Eval.True else lb
}.value
/**
* Check whether all elements satisfy the predicate.
*
* If there are no elements, the result is `true`.
*/
override def forall[A](fa: F[A])(p: A => Boolean): Boolean =
foldRight(fa, Eval.True) { (a, lb) =>
if (p(a)) lb else Eval.False
}.value
/**
* Check whether at least one element satisfies the effectful predicate.
*
* If there are no elements, the result is `false`. `existsM` short-circuits,
* i.e. once a `true` result is encountered, no further effects are produced.
*
* For example:
*
* {{{
* scala> import cats.implicits._
* scala> val F = Foldable[List]
* scala> F.existsM(List(1,2,3,4))(n => Option(n <= 4))
* res0: Option[Boolean] = Some(true)
*
* scala> F.existsM(List(1,2,3,4))(n => Option(n > 4))
* res1: Option[Boolean] = Some(false)
*
* scala> F.existsM(List(1,2,3,4))(n => if (n <= 2) Option(true) else Option(false))
* res2: Option[Boolean] = Some(true)
*
* scala> F.existsM(List(1,2,3,4))(n => if (n <= 2) Option(true) else None)
* res3: Option[Boolean] = Some(true)
*
* scala> F.existsM(List(1,2,3,4))(n => if (n <= 2) None else Option(true))
* res4: Option[Boolean] = None
* }}}
*/
def existsM[G[_], A](fa: F[A])(p: A => G[Boolean])(implicit G: Monad[G]): G[Boolean] =
G.tailRecM(Foldable.Source.fromFoldable(fa)(self)) { src =>
src.uncons match {
case Some((a, src)) => G.map(p(a))(bb => if (bb) Right(true) else Left(src.value))
case None => G.pure(Right(false))
}
}
/**
* Check whether all elements satisfy the effectful predicate.
*
* If there are no elements, the result is `true`. `forallM` short-circuits,
* i.e. once a `false` result is encountered, no further effects are produced.
*
* For example:
*
* {{{
* scala> import cats.implicits._
* scala> val F = Foldable[List]
* scala> F.forallM(List(1,2,3,4))(n => Option(n <= 4))
* res0: Option[Boolean] = Some(true)
*
* scala> F.forallM(List(1,2,3,4))(n => Option(n <= 1))
* res1: Option[Boolean] = Some(false)
*
* scala> F.forallM(List(1,2,3,4))(n => if (n <= 2) Option(true) else Option(false))
* res2: Option[Boolean] = Some(false)
*
* scala> F.forallM(List(1,2,3,4))(n => if (n <= 2) Option(false) else None)
* res3: Option[Boolean] = Some(false)
*
* scala> F.forallM(List(1,2,3,4))(n => if (n <= 2) None else Option(false))
* res4: Option[Boolean] = None
* }}}
*/
def forallM[G[_], A](fa: F[A])(p: A => G[Boolean])(implicit G: Monad[G]): G[Boolean] =
G.tailRecM(Foldable.Source.fromFoldable(fa)(self)) { src =>
src.uncons match {
case Some((a, src)) => G.map(p(a))(bb => if (!bb) Right(false) else Left(src.value))
case None => G.pure(Right(true))
}
}
/**
* Convert F[A] to a List[A].
*/
def toList[A](fa: F[A]): List[A] =
foldLeft(fa, mutable.ListBuffer.empty[A]) { (buf, a) =>
buf += a
}.toList
/**
* Separate this Foldable into a Tuple by a separating function `A => Either[B, C]`
* Equivalent to `Functor#map` and then `Alternative#separate`.
*
* {{{
* scala> import cats.implicits._
* scala> val list = List(1,2,3,4)
* scala> Foldable[List].partitionEither(list)(a => if (a % 2 == 0) Left(a.toString) else Right(a))
* res0: (List[String], List[Int]) = (List(2, 4),List(1, 3))
* scala> Foldable[List].partitionEither(list)(a => Right(a * 4))
* res1: (List[Nothing], List[Int]) = (List(),List(4, 8, 12, 16))
* }}}
*/
def partitionEither[A, B, C](fa: F[A])(f: A => Either[B, C])(implicit A: Alternative[F]): (F[B], F[C]) = {
implicit val mb: Monoid[F[B]] = A.algebra[B]
implicit val mc: Monoid[F[C]] = A.algebra[C]
foldMap(fa)(
a =>
f(a) match {
case Right(c) => (A.empty[B], A.pure(c))
case Left(b) => (A.pure(b), A.empty[C])
}
)
}
/**
* Convert F[A] to a List[A], only including elements which match `p`.
*/
def filter_[A](fa: F[A])(p: A => Boolean): List[A] =
foldLeft(fa, mutable.ListBuffer.empty[A]) { (buf, a) =>
if (p(a)) buf += a else buf
}.toList
/**
* Convert F[A] to a List[A], retaining only initial elements which
* match `p`.
*/
def takeWhile_[A](fa: F[A])(p: A => Boolean): List[A] =
foldRight(fa, Now(List.empty[A])) { (a, llst) =>
if (p(a)) llst.map(a :: _) else Now(Nil)
}.value
/**
* Convert F[A] to a List[A], dropping all initial elements which
* match `p`.
*/
def dropWhile_[A](fa: F[A])(p: A => Boolean): List[A] =
foldLeft(fa, mutable.ListBuffer.empty[A]) { (buf, a) =>
if (buf.nonEmpty || !p(a)) buf += a else buf
}.toList
/**
* Returns true if there are no elements. Otherwise false.
*/
override def isEmpty[A](fa: F[A]): Boolean =
foldRight(fa, Eval.True)((_, _) => Eval.False).value
override def nonEmpty[A](fa: F[A]): Boolean =
!isEmpty(fa)
/**
* Intercalate/insert an element between the existing elements while folding.
*
* {{{
* scala> import cats.implicits._
* scala> Foldable[List].intercalate(List("a","b","c"), "-")
* res0: String = a-b-c
* scala> Foldable[List].intercalate(List("a"), "-")
* res1: String = a
* scala> Foldable[List].intercalate(List.empty[String], "-")
* res2: String = ""
* scala> Foldable[Vector].intercalate(Vector(1,2,3), 1)
* res3: Int = 8
* }}}
*/
def intercalate[A](fa: F[A], a: A)(implicit A: Monoid[A]): A =
A.combineAll(intersperseList(toList(fa), a))
protected def intersperseList[A](xs: List[A], x: A): List[A] = {
val bld = List.newBuilder[A]
val it = xs.iterator
if (it.hasNext) {
bld += it.next
while (it.hasNext) {
bld += x
bld += it.next
}
}
bld.result
}
def compose[G[_]: Foldable]: Foldable[λ[α => F[G[α]]]] =
new ComposedFoldable[F, G] {
val F = self
val G = Foldable[G]
}
override def unorderedFold[A: CommutativeMonoid](fa: F[A]): A = fold(fa)
override def unorderedFoldMap[A, B: CommutativeMonoid](fa: F[A])(f: (A) => B): B =
foldMap(fa)(f)
/**
* Separate this Foldable into a Tuple by a separating function `A => H[B, C]` for some `Bifoldable[H]`
* Equivalent to `Functor#map` and then `Alternative#separate`.
*
* {{{
* scala> import cats.implicits._, cats.Foldable, cats.data.Const
* scala> val list = List(1,2,3,4)
* scala> Foldable[List].partitionBifold(list)(a => ("value " + a.toString(), if (a % 2 == 0) -a else a))
* res0: (List[String], List[Int]) = (List(value 1, value 2, value 3, value 4),List(1, -2, 3, -4))
* scala> Foldable[List].partitionBifold(list)(a => Const[Int, Nothing with Any](a))
* res1: (List[Int], List[Nothing with Any]) = (List(1, 2, 3, 4),List())
* }}}
*/
@noop
def partitionBifold[H[_, _], A, B, C](fa: F[A])(f: A => H[B, C])(implicit A: Alternative[F],
H: Bifoldable[H]): (F[B], F[C]) = {
import cats.instances.tuple._
implicit val mb: Monoid[F[B]] = A.algebra[B]
implicit val mc: Monoid[F[C]] = A.algebra[C]
foldMap[A, (F[B], F[C])](fa)(
a => H.bifoldMap[B, C, (F[B], F[C])](f(a))(b => (A.pure(b), A.empty[C]), c => (A.empty[B], A.pure(c)))
)
}
/**
* Separate this Foldable into a Tuple by an effectful separating function `A => G[H[B, C]]` for some `Bifoldable[H]`
* Equivalent to `Traverse#traverse` over `Alternative#separate`
*
* {{{
* scala> import cats.implicits._, cats.Foldable, cats.data.Const
* scala> val list = List(1,2,3,4)
* `Const`'s second parameter is never instantiated, so we can use an impossible type:
* scala> Foldable[List].partitionBifoldM(list)(a => Option(Const[Int, Nothing with Any](a)))
* res0: Option[(List[Int], List[Nothing with Any])] = Some((List(1, 2, 3, 4),List()))
* }}}
*/
@noop
def partitionBifoldM[G[_], H[_, _], A, B, C](
fa: F[A]
)(f: A => G[H[B, C]])(implicit A: Alternative[F], M: Monad[G], H: Bifoldable[H]): G[(F[B], F[C])] = {
import cats.instances.tuple._
implicit val mb: Monoid[F[B]] = A.algebra[B]
implicit val mc: Monoid[F[C]] = A.algebra[C]
foldMapM[G, A, (F[B], F[C])](fa)(
a =>
M.map(f(a)) {
H.bifoldMap[B, C, (F[B], F[C])](_)(b => (A.pure(b), A.empty[C]), c => (A.empty[B], A.pure(c)))
}
)
}
/**
* Separate this Foldable into a Tuple by an effectful separating function `A => G[Either[B, C]]`
* Equivalent to `Traverse#traverse` over `Alternative#separate`
*
* {{{
* scala> import cats.implicits._, cats.Foldable, cats.Eval
* scala> val list = List(1,2,3,4)
* scala> val partitioned1 = Foldable[List].partitionEitherM(list)(a => if (a % 2 == 0) Eval.now(Either.left[String, Int](a.toString)) else Eval.now(Either.right[String, Int](a)))
* Since `Eval.now` yields a lazy computation, we need to force it to inspect the result:
* scala> partitioned1.value
* res0: (List[String], List[Int]) = (List(2, 4),List(1, 3))
* scala> val partitioned2 = Foldable[List].partitionEitherM(list)(a => Eval.later(Either.right(a * 4)))
* scala> partitioned2.value
* res1: (List[Nothing], List[Int]) = (List(),List(4, 8, 12, 16))
* }}}
*/
@noop
def partitionEitherM[G[_], A, B, C](fa: F[A])(f: A => G[Either[B, C]])(implicit A: Alternative[F],
M: Monad[G]): G[(F[B], F[C])] = {
import cats.instances.either._
partitionBifoldM[G, Either, A, B, C](fa)(f)(A, M, Bifoldable[Either])
}
}
object Foldable {
private val sentinel: Function1[Any, Any] = new scala.runtime.AbstractFunction1[Any, Any] { def apply(a: Any) = this }
def iterateRight[A, B](iterable: Iterable[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = {
def loop(it: Iterator[A]): Eval[B] =
Eval.defer(if (it.hasNext) f(it.next, loop(it)) else lb)
Eval.always(iterable.iterator).flatMap(loop)
}
def iterateRightDefer[G[_]: Defer, A, B](iterable: Iterable[A], lb: G[B])(f: (A, G[B]) => G[B]): G[B] = {
def loop(it: Iterator[A]): G[B] =
Defer[G].defer(if (it.hasNext) f(it.next(), Defer[G].defer(loop(it))) else Defer[G].defer(lb))
Defer[G].defer(loop(iterable.iterator))
}
/**
* Isomorphic to
*
* type Source[+A] = () => Option[(A, Source[A])]
*
* (except that recursive type aliases are not allowed).
*
* It could be made a value class after
* https://github.com/scala/bug/issues/9600 is resolved.
*/
sealed abstract private[cats] class Source[+A] {
def uncons: Option[(A, Eval[Source[A]])]
}
private[cats] object Source {
val Empty: Source[Nothing] = new Source[Nothing] {
def uncons = None
}
def cons[A](a: A, src: Eval[Source[A]]): Source[A] = new Source[A] {
def uncons = Some((a, src))
}
def fromFoldable[F[_], A](fa: F[A])(implicit F: Foldable[F]): Source[A] =
F.foldRight[A, Source[A]](fa, Now(Empty))((a, evalSrc) => Later(cons(a, evalSrc))).value
}
}