PageRenderTime 64ms CodeModel.GetById 17ms app.highlight 40ms RepoModel.GetById 2ms app.codeStats 0ms

/core/src/main/scala/scalaz/Foldable.scala

http://github.com/scalaz/scalaz
Scala | 480 lines | 288 code | 79 blank | 113 comment | 49 complexity | 893476049cdf99669b2075473126fefe MD5 | raw file
  1package scalaz
  2
  3////
  4/**
  5 * A type parameter implying the ability to extract zero or more
  6 * values of that type.
  7 */
  8////
  9trait Foldable[F[_]]  { self =>
 10  ////
 11
 12  /** Map each element of the structure to a [[scalaz.Monoid]], and combine the results. */
 13  def foldMap[A,B](fa: F[A])(f: A => B)(implicit F: Monoid[B]): B
 14  /** As `foldMap` but returning `None` if the foldable is empty and `Some` otherwise */
 15  def foldMap1Opt[A,B](fa: F[A])(f: A => B)(implicit F: Semigroup[B]): Option[B] = {
 16    import std.option._
 17    foldMap(fa)(x => some(f(x)))
 18  }
 19
 20  /**Right-associative fold of a structure. */
 21  def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B): B
 22
 23  /**The composition of Foldables `F` and `G`, `[x]F[G[x]]`, is a Foldable */
 24  def compose[G[_]](implicit G0: Foldable[G]): Foldable[λ[α => F[G[α]]]] =
 25    new CompositionFoldable[F, G] {
 26      implicit def F = self
 27      implicit def G = G0
 28    }
 29
 30  /** The composition of Foldable `F` and Bifoldable `G`, `[x, y]F[G[x, y]]`, is a Bifoldable */
 31  def bicompose[G[_, _]: Bifoldable]: Bifoldable[λ[(α, β) => F[G[α, β]]]] =
 32    new CompositionFoldableBifoldable[F, G] {
 33      def F = self
 34      def G = implicitly
 35    }
 36
 37  /**The product of Foldables `F` and `G`, `[x](F[x], G[x]])`, is a Foldable */
 38  def product[G[_]](implicit G0: Foldable[G]): Foldable[λ[α => (F[α], G[α])]] =
 39    new ProductFoldable[F, G] {
 40      implicit def F = self
 41      implicit def G = G0
 42    }
 43
 44  /**The product of Foldable `F` and Foldable1 `G`, `[x](F[x], G[x]])`, is a Foldable1 */
 45  def product0[G[_]](implicit G0: Foldable1[G]): Foldable1[λ[α => (F[α], G[α])]] =
 46    new ProductFoldable1R[F, G] {
 47      def F = self
 48      def G = G0
 49    }
 50
 51  /**Left-associative fold of a structure. */
 52  def foldLeft[A, B](fa: F[A], z: B)(f: (B, A) => B): B = {
 53    import Dual._, Endo._, syntax.std.all._
 54    Tag.unwrap(foldMap(fa)((a: A) => Dual(Endo.endo(f.flip.curried(a))))(dualMonoid)) apply (z)
 55  }
 56
 57  /**Right-associative, monadic fold of a structure. */
 58  def foldRightM[G[_], A, B](fa: F[A], z: => B)(f: (A, => B) => G[B])(implicit M: Monad[G]): G[B] =
 59    foldLeft[A, B => G[B]](fa, M.point(_))((b, a) => w => M.bind(f(a, w))(b))(z)
 60
 61  /**Left-associative, monadic fold of a structure. */
 62  def foldLeftM[G[_], A, B](fa: F[A], z: B)(f: (B, A) => G[B])(implicit M: Monad[G]): G[B] =
 63    foldRight[A, B => G[B]](fa, M.point(_))((a, b) => w => M.bind(f(w, a))(b))(z)
 64
 65  /** Specialization of foldRightM when `B` has a `Monoid`. */
 66  def foldMapM[G[_], A, B](fa: F[A])(f: A => G[B])(implicit B: Monoid[B], G: Monad[G]): G[B] =
 67    foldRightM[G, A, B](fa, B.zero)((a, b2) => G.map(f(a))(b1 => B.append(b1, b2)))
 68
 69  /** Combine the elements of a structure using a monoid. */
 70  def fold[M: Monoid](t: F[M]): M = foldMap[M, M](t)(x => x)
 71
 72  /** Like `fold` but returning `None` if the foldable is empty and `Some` otherwise */
 73  def fold1Opt[A: Semigroup](fa: F[A]): Option[A] = foldMap1Opt(fa)(a => a)
 74
 75  /** Strict traversal in an applicative functor `M` that ignores the result of `f`. */
 76  def traverse_[M[_], A, B](fa: F[A])(f: A => M[B])(implicit a: Applicative[M]): M[Unit] =
 77    foldLeft(fa, a.pure(()))((x, y) => a.ap(f(y))(a.map(x)(_ => _ => ())))
 78
 79  /** A version of `traverse_` that infers the type constructor `M`. */
 80  final def traverseU_[A, GB](fa: F[A])(f: A => GB)(implicit G: Unapply[Applicative, GB]): G.M[Unit] =
 81    traverse_[G.M, A, G.A](fa)(G.leibniz.onF(f))(G.TC)
 82
 83  /** `traverse_` specialized to `State` **/
 84  def traverseS_[S, A, B](fa: F[A])(f: A => State[S, B]): State[S, Unit] =
 85    State{s: S =>
 86      (foldLeft(fa, s)((s, a) => f(a)(s)._1), ())
 87    }
 88
 89  /** Strict sequencing in an applicative functor `M` that ignores the value in `fa`. */
 90  def sequence_[M[_], A](fa: F[M[A]])(implicit a: Applicative[M]): M[Unit] =
 91    traverse_(fa)(x => x)
 92
 93  /** `sequence_` specialized to `State` **/
 94  def sequenceS_[S, A](fga: F[State[S, A]]): State[S, Unit] =
 95    traverseS_(fga)(x => x)
 96
 97  /** `sequence_` for Free. collapses into a single Free **/
 98  def sequenceF_[M[_], A](ffa: F[Free[M, A]]): Free[M, Unit] =
 99    foldLeft[Free[M,A],Free[M,Unit]](ffa, Free.pure[M, Unit](()))((c,d) => c.flatMap(_ => d.map(_ => ())))
100
101  /**Curried version of `foldRight` */
102  final def foldr[A, B](fa: F[A], z: => B)(f: A => (=> B) => B): B = foldRight(fa, z)((a, b) => f(a)(b))
103  def foldMapRight1Opt[A, B](fa: F[A])(z: A => B)(f: (A, => B) => B): Option[B] =
104    foldRight(fa, None: Option[B])((a, optB) =>
105      optB map (f(a, _)) orElse Some(z(a)))
106  def foldRight1Opt[A](fa: F[A])(f: (A, => A) => A): Option[A] =
107    foldMapRight1Opt(fa)(identity)(f)
108  def foldr1Opt[A](fa: F[A])(f: A => (=> A) => A): Option[A] = foldRight(fa, None: Option[A])((a, optA) => optA map (aa => f(a)(aa)) orElse Some(a))
109
110  /**Curried version of `foldLeft` */
111  final def foldl[A, B](fa: F[A], z: B)(f: B => A => B): B = foldLeft(fa, z)((b, a) => f(b)(a))
112  def foldMapLeft1Opt[A, B](fa: F[A])(z: A => B)(f: (B, A) => B): Option[B] =
113    foldLeft(fa, None: Option[B])((optB, a) =>
114      optB map (f(_, a)) orElse Some(z(a)))
115  def foldLeft1Opt[A](fa: F[A])(f: (A, A) => A): Option[A] =
116    foldMapLeft1Opt(fa)(identity)(f)
117  def foldl1Opt[A](fa: F[A])(f: A => A => A): Option[A] = foldLeft(fa, None: Option[A])((optA, a) => optA map (aa => f(aa)(a)) orElse Some(a))
118
119  /**Curried version of `foldRightM` */
120  final def foldrM[G[_], A, B](fa: F[A], z: => B)(f: A => ( => B) => G[B])(implicit M: Monad[G]): G[B] =
121    foldRightM(fa, z)((a, b) => f(a)(b))
122
123  /**Curried version of `foldLeftM` */
124  final def foldlM[G[_], A, B](fa: F[A], z: => B)(f: B => A => G[B])(implicit M: Monad[G]): G[B] =
125    foldLeftM(fa, z)((b, a) => f(b)(a))
126
127  /** map elements in a Foldable with a monadic function and return the first element that is mapped successfully */
128  final def findMapM[M[_]: Monad, A, B](fa: F[A])(f: A => M[Option[B]]): M[Option[B]] =
129    toEphemeralStream(fa) findMapM f
130
131  def findLeft[A](fa: F[A])(f: A => Boolean): Option[A] =
132    foldLeft[A, Option[A]](fa, None)((b, a) => b.orElse(if(f(a)) Some(a) else None))
133
134  def findRight[A](fa: F[A])(f: A => Boolean): Option[A] =
135    foldRight[A, Option[A]](fa, None)((a, b) => b.orElse(if(f(a)) Some(a) else None))
136
137  /** Alias for `length`. */
138  final def count[A](fa: F[A]): Int = length(fa)
139
140  /** Deforested alias for `toStream(fa).size`. */
141  def length[A](fa: F[A]): Int = foldLeft(fa, 0)((b, _) => b + 1)
142
143  /**
144   * @return the element at index `i` in a `Some`, or `None` if the given index falls outside of the range
145   */
146  def index[A](fa: F[A], i: Int): Option[A] =
147    foldLeft[A, (Int, Option[A])](fa, (0, None)) {
148      case ((idx, elem), curr) =>
149        (idx + 1, elem orElse { if (idx == i) Some(curr) else None })
150    }._2
151
152  /**
153   * @return the element at index `i`, or `default` if the given index falls outside of the range
154   */
155  def indexOr[A](fa: F[A], default: => A, i: Int): A =
156    index(fa, i) getOrElse default
157
158  def toList[A](fa: F[A]): List[A] = {
159    foldLeft(fa, List.newBuilder[A])(_ += _).result
160  }
161  def toVector[A](fa: F[A]): Vector[A] = {
162    foldLeft(fa, Vector.newBuilder[A])(_ += _).result
163  }
164  def toSet[A](fa: F[A]): Set[A] = {
165    foldLeft(fa, Set.newBuilder[A])(_ += _).result
166  }
167  def toStream[A](fa: F[A]): Stream[A] = foldRight[A, Stream[A]](fa, Stream.empty)(Stream.cons(_, _))
168
169  def toIList[A](fa: F[A]): IList[A] =
170    foldLeft(fa, IList.empty[A])((t, h) => h :: t).reverse
171
172  def toEphemeralStream[A](fa: F[A]): EphemeralStream[A] =
173    foldRight(fa, EphemeralStream.emptyEphemeralStream[A])(EphemeralStream.cons(_, _))
174
175  /** Whether all `A`s in `fa` yield true from `p`. */
176  def all[A](fa: F[A])(p: A => Boolean): Boolean = foldRight(fa, true)(p(_) && _)
177  /** `all` with monadic traversal. */
178  def allM[G[_], A](fa: F[A])(p: A => G[Boolean])(implicit G: Monad[G]): G[Boolean] =
179    foldRight(fa, G.point(true))((a, b) => G.bind(p(a))(q => if(q) b else G.point(false)))
180  /** Whether any `A`s in `fa` yield true from `p`. */
181  def any[A](fa: F[A])(p: A => Boolean): Boolean = foldRight(fa, false)(p(_) || _)
182  /** `any` with monadic traversal. */
183  def anyM[G[_], A](fa: F[A])(p: A => G[Boolean])(implicit G: Monad[G]): G[Boolean] =
184    foldRight(fa, G.point(false))((a, b) => G.bind(p(a))(q => if(q) G.point(true) else b))
185
186  def filterLength[A](fa: F[A])(f: A => Boolean): Int =
187    foldLeft(fa, 0)((b, a) => (if (f(a)) 1 else 0) + b)
188
189  import Ordering.{GT, LT}
190  import std.option.{some, none}
191
192  /** The greatest element of `fa`, or None if `fa` is empty. */
193  def maximum[A: Order](fa: F[A]): Option[A] =
194    foldLeft(fa, none[A]) {
195      case (None, y) => some(y)
196      case (Some(x), y) => some(if (Order[A].order(x, y) == GT) x else y)
197    }
198
199  /** The greatest value of `f(a)` for each element `a` of `fa`, or None if `fa` is empty. */
200  def maximumOf[A, B: Order](fa: F[A])(f: A => B): Option[B] =
201    foldLeft(fa, none[B]) {
202      case (None, a) => some(f(a))
203      case (Some(b), aa) => val bb = f(aa); some(if (Order[B].order(b, bb) == GT) b else bb)
204    }
205
206  /** The element `a` of `fa` which yields the greatest value of `f(a)`, or None if `fa` is empty. */
207  def maximumBy[A, B: Order](fa: F[A])(f: A => B): Option[A] =
208    foldLeft(fa, none[(A, B)]) {
209      case (None, a) => some(a -> f(a))
210      case (Some(x @ (a, b)), aa) => val bb = f(aa); some(if (Order[B].order(b, bb) == GT) x else aa -> bb)
211    } map (_._1)
212
213  /** The smallest element of `fa`, or None if `fa` is empty. */
214  def minimum[A: Order](fa: F[A]): Option[A] =
215    foldLeft(fa, none[A]) {
216      case (None, y) => some(y)
217      case (Some(x), y) => some(if (Order[A].order(x, y) == LT) x else y)
218    }
219
220  /** The smallest value of `f(a)` for each element `a` of `fa`, or None if `fa` is empty. */
221  def minimumOf[A, B: Order](fa: F[A])(f: A => B): Option[B] =
222    foldLeft(fa, none[B]) {
223      case (None, a) => some(f(a))
224      case (Some(b), aa) => val bb = f(aa); some(if (Order[B].order(b, bb) == LT) b else bb)
225    }
226
227  /** The element `a` of `fa` which yields the smallest value of `f(a)`, or None if `fa` is empty. */
228  def minimumBy[A, B: Order](fa: F[A])(f: A => B): Option[A] =
229    foldLeft(fa, none[(A, B)]) {
230      case (None, a) => some(a -> f(a))
231      case (Some(x @ (a, b)), aa) => val bb = f(aa); some(if (Order[B].order(b, bb) == LT) x else aa -> bb)
232    } map (_._1)
233
234  /** The smallest and largest elements of `fa` or None if `fa` is empty */
235  def extrema[A: Order](fa: F[A]): Option[(A, A)] =
236    extremaBy(fa)(identity)
237
238  /** The smallest and largest values of `f(a)` for each element `a` of `fa` , or None if `fa` is empty */
239  def extremaOf[A, B: Order](fa: F[A])(f: A => B): Option[(B, B)] =
240    foldMapLeft1Opt(fa) { a =>
241      val b = f(a)
242      (b, b)
243    } {
244      case (x @ (bmin, bmax), a) =>
245        val b = f(a)
246        if (Order[B].order(b, bmin) == LT) (b, bmax)
247        else if (Order[B].order(b, bmax) == GT) (bmin, b)
248        else x
249    }
250
251  /** The elements (amin, amax) of `fa` which yield the smallest and largest values of `f(a)`, respectively, or None if `fa` is empty */
252  def extremaBy[A, B: Order](fa: F[A])(f: A => B): Option[(A, A)] =
253    foldMapLeft1Opt(fa) { a =>
254        val b = f(a)
255        (a, a, b, b)
256    } {
257      case (x @ ((amin, amax, bmin, bmax)), a) =>
258        val b = f(a)
259        val greaterThanOrEq = Order[B].greaterThanOrEqual(b, bmax)
260        if(Order[B].lessThanOrEqual(b, bmin)) {
261          if(greaterThanOrEq) {
262            (a, a, b, b)
263          } else {
264            (a, amax, b, bmax)
265          }
266        } else {
267          if(greaterThanOrEq) {
268            (amin, a, bmin, b)
269          } else {
270            x
271          }
272        }
273    } map {
274      case (amin, amax, _, _) => (amin, amax)
275    }
276
277  def sumr[A](fa: F[A])(implicit A: Monoid[A]): A =
278    foldRight(fa, A.zero)(A.append)
279
280  def sumr1Opt[A](fa: F[A])(implicit A: Semigroup[A]): Option[A] =
281    foldRight1Opt(fa)(A.append(_, _))
282
283  def suml[A](fa: F[A])(implicit A: Monoid[A]): A =
284    foldLeft(fa, A.zero)(A.append(_, _))
285
286  def suml1Opt[A](fa: F[A])(implicit A: Semigroup[A]): Option[A] =
287    foldLeft1Opt(fa)(A.append(_, _))
288
289  /**
290   * Map elements to `G[B]` and sum using a polymorphic monoid ([[PlusEmpty]]).
291   * Should support early termination, i.e. mapping and summing
292   * no more elements than is needed to determine the result.
293   */
294  def psumMap[A, B, G[_]](fa: F[A])(f: A => G[B])(implicit G: PlusEmpty[G]): G[B] =
295    foldMap(fa)(f)(G.monoid)
296
297  /**
298   * Sum using a polymorphic monoid ([[PlusEmpty]]).
299   * Should support early termination, i.e. summing no more
300   * elements than is needed to determine the result.
301   */
302  def psum[G[_], A](fa: F[G[A]])(implicit G: PlusEmpty[G]): G[A] =
303    fold(fa)(G.monoid)
304
305  /** Alias for [[psum]]. `asum` is the name used in Haskell. */
306  final def asum[G[_], A](fa: F[G[A]])(implicit G: PlusEmpty[G]): G[A] =
307    psum(fa)
308
309  def longDigits[A](fa: F[A])(implicit d: A <:< Digit): Long = foldLeft(fa, 0L)((n, a) => n * 10L + (a: Digit))
310  /** Deforested alias for `toStream(fa).isEmpty`. */
311  def empty[A](fa: F[A]): Boolean = all(fa)(_ => false)
312  /** Whether `a` is an element of `fa`. */
313  def element[A: Equal](fa: F[A], a: A): Boolean = any(fa)(Equal[A].equal(a, _))
314  /** Insert an `A` between every A, yielding the sum. */
315  def intercalate[A](fa: F[A], a: A)(implicit A: Monoid[A]): A =
316    (foldRight(fa, none[A]) {(l, oa) =>
317      some(A.append(l, oa map (A.append(a, _)) getOrElse A.zero))
318    }).getOrElse(A.zero)
319
320  /**
321   * Splits the elements into groups that alternatively satisfy and don't satisfy the predicate p.
322   */
323  def splitWith[A](fa: F[A])(p: A => Boolean): List[NonEmptyList[A]] =
324    foldRight(fa, Maybe.empty[(NonEmptyList[NonEmptyList[A]], Boolean)])((a, b) => {
325      val pa = p(a)
326      Maybe.just(
327        (b match {
328          case Maybe.Just((x, q)) => if (pa == q) NonEmptyList.nel(a <:: x.head, x.tail) else NonEmptyList(a) <:: x
329          case Maybe.Empty() => NonEmptyList(NonEmptyList(a))
330        }, pa))
331    }).cata(_._1.list.toList, List.empty)
332
333  /**
334    * Splits the elements into groups that produce the same result by a function f.
335    */
336  def splitBy[A, B: Equal](fa: F[A])(f: A => B): IList[(B, NonEmptyList[A])] =
337    foldRight(fa, IList[(B, NonEmptyList[A])]())((a, bas) => {
338      val fa = f(a)
339      bas match {
340        case INil() => IList.single((fa, NonEmptyList.nel(a, IList.empty)))
341        case ICons((b, as), tail) => if (Equal[B].equal(fa, b)) ICons((b, a <:: as), tail) else ICons((fa, NonEmptyList.nel(a, IList.empty)), bas)
342      }
343    })
344
345  /**
346    * Splits into groups of elements that are transitively dependant by a relation r.
347    */
348  def splitByRelation[A](fa: F[A])(r: (A, A) => Boolean): IList[NonEmptyList[A]] =
349    foldRight(fa, IList[NonEmptyList[A]]())((a, neas) => {
350      neas match {
351        case INil() => IList.single(NonEmptyList.nel(a, IList.empty))
352        case ICons(nea, tail) => if (r(a, nea.head)) ICons(a <:: nea, tail) else ICons(NonEmptyList.nel(a, IList.empty), neas)
353      }
354    })
355
356  /**
357   * Selects groups of elements that satisfy p and discards others.
358   */
359  def selectSplit[A](fa: F[A])(p: A => Boolean): List[NonEmptyList[A]] = {
360    import scalaz.syntax.foldable._
361
362    def squash(t: (List[NonEmptyList[A]], IList[A])): List[NonEmptyList[A]] = t._2.toNel.toList ::: t._1
363
364    squash(foldRight(fa, (List.empty[NonEmptyList[A]], IList.empty[A]))((a, l) =>
365      if (p(a)) (l._1, a :: l._2)
366      else (squash(l), IList.empty)
367    ))
368  }
369
370  /** ``O(n log n)`` complexity */
371  def distinct[A](fa: F[A])(implicit A: Order[A]): IList[A] =
372    foldLeft(fa, (ISet.empty[A],IList.empty[A])) {
373      case ((seen, acc), a) =>
374        if (seen.notMember(a))
375          (seen.insert(a), a :: acc)
376        else (seen, acc)
377    }._2.reverse
378
379  /** ``O(n^2^)`` complexity */
380  def distinctE[A](fa: F[A])(implicit A: Equal[A]): IList[A] =
381    foldLeft(fa, IList.empty[A]) {
382      case (seen, a) =>
383        if (!IList.instances.element(seen,a))
384          a :: seen
385        else seen
386    }.reverse
387
388  def distinctBy[A, B: Equal](fa: F[A])(f: A => B): IList[A] =
389    distinctE(fa)(Equal.equalBy(f))
390
391  def collapse[X[_], A](x: F[A])(implicit A: ApplicativePlus[X]): X[A] =
392    foldRight(x, A.empty[A])((a, b) => A.plus(A.point(a), b))
393
394  trait FoldableLaw {
395    import std.vector._
396
397    /** Left fold is consistent with foldMap. */
398    def leftFMConsistent[A: Equal](fa: F[A]): Boolean =
399      Equal[Vector[A]].equal(foldMap(fa)(Vector(_)),
400                             foldLeft(fa, Vector.empty[A])(_ :+ _))
401
402    /** Right fold is consistent with foldMap. */
403    def rightFMConsistent[A: Equal](fa: F[A]): Boolean =
404      Equal[Vector[A]].equal(foldMap(fa)(Vector(_)),
405                             foldRight(fa, Vector.empty[A])(_ +: _))
406  }
407  def foldableLaw = new FoldableLaw {}
408
409  ////
410  val foldableSyntax: scalaz.syntax.FoldableSyntax[F] =
411    new scalaz.syntax.FoldableSyntax[F] { def F = Foldable.this }
412}
413
414object Foldable {
415  @inline def apply[F[_]](implicit F: Foldable[F]): Foldable[F] = F
416
417
418
419  ////
420
421  def fromIso[F[_], G[_]](D: F ~> G)(implicit E: Foldable[G]): Foldable[F] =
422    new IsomorphismFoldable[F, G] {
423      override def G: Foldable[G] = E
424      override def naturalTrans: F ~> G = D
425    }
426
427  /**
428   * Template trait to define `Foldable` in terms of `foldMap`.
429   *
430   * Example:
431   * {{{
432   * new Foldable[Option] with Foldable.FromFoldMap[Option] {
433   *   def foldMap[A, B](fa: Option[A])(f: A => B)(implicit F: Monoid[B]) = fa match {
434   *     case Some(a) => f(a)
435   *     case None    => F.zero
436   *   }
437   * }
438   * }}}
439   */
440  trait FromFoldMap[F[_]] extends Foldable[F] {
441    override def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B) =
442      foldMap(fa)((a: A) => Endo.endoByName[B](f(a, _))) apply z
443  }
444
445  /**
446   * Template trait to define `Foldable` in terms of `foldRight`
447   *
448   * Example:
449   * {{{
450   * new Foldable[Option] with Foldable.FromFoldr[Option] {
451   *   def foldRight[A, B](fa: Option[A], z: B)(f: (A, => B) => B) = fa match {
452   *     case Some(a) => f(a, z)
453   *     case None => z
454   *   }
455   * }
456   * }}}
457   */
458  trait FromFoldr[F[_]] extends Foldable[F] {
459    override def foldMap[A, B](fa: F[A])(f: A => B)(implicit F: Monoid[B]) =
460      foldRight[A, B](fa, F.zero)((x, y) => F.append(f(x),  y))
461  }
462
463  ////
464}
465
466trait IsomorphismFoldable[F[_], G[_]] extends Foldable[F] {
467  implicit def G: Foldable[G]
468  ////
469  protected[this] def naturalTrans: F ~> G
470
471  override def foldMap[A, B](fa: F[A])(f: A => B)(implicit F: Monoid[B]): B =
472    G.foldMap(naturalTrans(fa))(f)
473
474  override def foldLeft[A, B](fa: F[A], z: B)(f: (B, A) => B): B =
475    G.foldLeft(naturalTrans(fa), z)(f)
476
477  override def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B): B =
478    G.foldRight[A, B](naturalTrans(fa), z)(f)
479  ////
480}