/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

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