Skip to content

Commit

Permalink
Use Foldable foldRight for Traverse and TraverseFilter. (#3015)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanaka takaya authored and LukaJCB committed Nov 6, 2019
1 parent 254ec63 commit ed73246
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 13 deletions.
32 changes: 21 additions & 11 deletions core/src/main/scala/cats/data/Chain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -685,10 +685,14 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
new Traverse[Chain] with Alternative[Chain] with Monad[Chain] with CoflatMap[Chain] with Align[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
Expand All @@ -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)
Expand Down Expand Up @@ -802,12 +806,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

}

Expand Down
6 changes: 4 additions & 2 deletions core/src/main/scala/cats/instances/list.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,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
Expand Down

0 comments on commit ed73246

Please sign in to comment.