From 663202cf3ec7ce122d6789188e07d689c53646fd Mon Sep 17 00:00:00 2001 From: "ta.tanaka" Date: Wed, 28 Aug 2019 21:13:49 +0900 Subject: [PATCH] Use Foldable foldRight for Traverse and TraverseFilter. --- core/src/main/scala/cats/data/Chain.scala | 32 ++++++++++++------- core/src/main/scala/cats/instances/list.scala | 6 ++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/core/src/main/scala/cats/data/Chain.scala b/core/src/main/scala/cats/data/Chain.scala index 7a9cacf0c0..f209334755 100644 --- a/core/src/main/scala/cats/data/Chain.scala +++ b/core/src/main/scala/cats/data/Chain.scala @@ -685,10 +685,14 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 { new Traverse[Chain] with Alternative[Chain] with Monad[Chain] with CoflatMap[Chain] { def foldLeft[A, B](fa: Chain[A], b: B)(f: (B, A) => B): B = fa.foldLeft(b)(f) - def foldRight[A, B](fa: Chain[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - Eval.defer(fa.foldRight(lb) { (a, lb) => - Eval.defer(f(a, lb)) - }) + def foldRight[A, B](fa: Chain[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = { + def loop(as: Chain[A]): Eval[B] = + as match { + case Chain.nil => lb + case h ==: t => f(h, Eval.defer(loop(t))) + } + Eval.defer(loop(fa)) + } override def map[A, B](fa: Chain[A])(f: A => B): Chain[B] = fa.map(f) override def toList[A](fa: Chain[A]): List[A] = fa.toList @@ -711,9 +715,9 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 { } def traverse[G[_], A, B](fa: Chain[A])(f: A => G[B])(implicit G: Applicative[G]): G[Chain[B]] = - fa.foldRight[G[Chain[B]]](G.pure(nil)) { (a, gcatb) => - G.map2(f(a), gcatb)(_ +: _) - } + foldRight[A, G[Chain[B]]](fa, Always(G.pure(nil))) { (a, lglb) => + G.map2Eval(f(a), lglb)(_ +: _) + }.value def empty[A]: Chain[A] = Chain.nil def combineK[A](c: Chain[A], c2: Chain[A]): Chain[A] = Chain.concat(c, c2) def pure[A](a: A): Chain[A] = Chain.one(a) @@ -781,12 +785,18 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 { override def flattenOption[A](fa: Chain[Option[A]]): Chain[A] = fa.collect { case Some(a) => a } def traverseFilter[G[_], A, B](fa: Chain[A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Chain[B]] = - fa.foldRight(G.pure(Chain.empty[B]))( - (a, gcb) => G.map2(f(a), gcb)((ob, cb) => ob.fold(cb)(_ +: cb)) - ) + traverse + .foldRight(fa, Eval.now(G.pure(Chain.empty[B])))( + (x, xse) => G.map2Eval(f(x), xse)((i, o) => i.fold(o)(_ +: o)) + ) + .value override def filterA[G[_], A](fa: Chain[A])(f: A => G[Boolean])(implicit G: Applicative[G]): G[Chain[A]] = - fa.foldRight(G.pure(Chain.empty[A]))((a, gca) => G.map2(f(a), gca)((b, chain) => if (b) a +: chain else chain)) + traverse + .foldRight(fa, Eval.now(G.pure(Chain.empty[A])))( + (x, xse) => G.map2Eval(f(x), xse)((b, chain) => if (b) x +: chain else chain) + ) + .value } diff --git a/core/src/main/scala/cats/instances/list.scala b/core/src/main/scala/cats/instances/list.scala index 975fa14519..9588bc0565 100644 --- a/core/src/main/scala/cats/instances/list.scala +++ b/core/src/main/scala/cats/instances/list.scala @@ -165,13 +165,15 @@ private[instances] trait ListInstancesBinCompat0 { override def flattenOption[A](fa: List[Option[A]]): List[A] = fa.flatten def traverseFilter[G[_], A, B](fa: List[A])(f: (A) => G[Option[B]])(implicit G: Applicative[G]): G[List[B]] = - fa.foldRight(Eval.now(G.pure(List.empty[B])))( + traverse + .foldRight(fa, Eval.now(G.pure(List.empty[B])))( (x, xse) => G.map2Eval(f(x), xse)((i, o) => i.fold(o)(_ :: o)) ) .value override def filterA[G[_], A](fa: List[A])(f: (A) => G[Boolean])(implicit G: Applicative[G]): G[List[A]] = - fa.foldRight(Eval.now(G.pure(List.empty[A])))( + traverse + .foldRight(fa, Eval.now(G.pure(List.empty[A])))( (x, xse) => G.map2Eval(f(x), xse)((b, list) => if (b) x :: list else list) ) .value