Skip to content

Commit

Permalink
Use lazy iterator for align
Browse files Browse the repository at this point in the history
  • Loading branch information
LukaJCB committed Oct 15, 2019
1 parent 7a772b4 commit e249b96
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 37 deletions.
44 changes: 22 additions & 22 deletions core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -334,28 +334,28 @@ sealed abstract private[data] class NonEmptyLazyListInstances extends NonEmptyLa
with NonEmptyTraverse[NonEmptyLazyList]
with SemigroupK[NonEmptyLazyList]
with Align[NonEmptyLazyList] =
new AbstractNonEmptyInstances[LazyList, NonEmptyLazyList] {

def extract[A](fa: NonEmptyLazyList[A]): A = fa.head

def nonEmptyTraverse[G[_]: Apply, A, B](fa: NonEmptyLazyList[A])(f: A => G[B]): G[NonEmptyLazyList[B]] =
Foldable[LazyList]
.reduceRightToOption[A, G[LazyList[B]]](fa.tail)(a => Apply[G].map(f(a))(LazyList.apply(_))) { (a, lglb) =>
Apply[G].map2Eval(f(a), lglb)(_ +: _)
}
.map {
case None => Apply[G].map(f(fa.head))(h => create(LazyList(h)))
case Some(gtail) => Apply[G].map2(f(fa.head), gtail)((h, t) => create(LazyList(h) ++ t))
}
.value

def reduceLeftTo[A, B](fa: NonEmptyLazyList[A])(f: A => B)(g: (B, A) => B): B = fa.reduceLeftTo(f)(g)

def reduceRightTo[A, B](fa: NonEmptyLazyList[A])(f: A => B)(g: (A, cats.Eval[B]) => cats.Eval[B]): cats.Eval[B] =
Eval.defer(fa.reduceRightTo(a => Eval.now(f(a))) { (a, b) =>
Eval.defer(g(a, b))
})
}
new AbstractNonEmptyInstances[LazyList, NonEmptyLazyList] {

def extract[A](fa: NonEmptyLazyList[A]): A = fa.head

def nonEmptyTraverse[G[_]: Apply, A, B](fa: NonEmptyLazyList[A])(f: A => G[B]): G[NonEmptyLazyList[B]] =
Foldable[LazyList]
.reduceRightToOption[A, G[LazyList[B]]](fa.tail)(a => Apply[G].map(f(a))(LazyList.apply(_))) { (a, lglb) =>
Apply[G].map2Eval(f(a), lglb)(_ +: _)
}
.map {
case None => Apply[G].map(f(fa.head))(h => create(LazyList(h)))
case Some(gtail) => Apply[G].map2(f(fa.head), gtail)((h, t) => create(LazyList(h) ++ t))
}
.value

def reduceLeftTo[A, B](fa: NonEmptyLazyList[A])(f: A => B)(g: (B, A) => B): B = fa.reduceLeftTo(f)(g)

def reduceRightTo[A, B](fa: NonEmptyLazyList[A])(f: A => B)(g: (A, cats.Eval[B]) => cats.Eval[B]): cats.Eval[B] =
Eval.defer(fa.reduceRightTo(a => Eval.now(f(a))) { (a, b) =>
Eval.defer(g(a, b))
})
}

implicit def catsDataOrderForNonEmptyLazyList[A: Order]: Order[NonEmptyLazyList[A]] =
Order[LazyList[A]].asInstanceOf[Order[NonEmptyLazyList[A]]]
Expand Down
31 changes: 17 additions & 14 deletions core/src/main/scala-2.13+/cats/instances/lazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import cats.syntax.show._
import cats.data.Ior
import cats.data.ZipLazyList


import scala.annotation.tailrec

trait LazyListInstances extends cats.kernel.instances.LazyListInstances {

implicit val catsStdInstancesForLazyList
: Traverse[LazyList] with Alternative[LazyList] with Monad[LazyList] with CoflatMap[LazyList] with Align[LazyList] =
new Traverse[LazyList] with Alternative[LazyList] with Monad[LazyList] with CoflatMap[LazyList]
with Align[LazyList] {
new Traverse[LazyList]
with Alternative[LazyList]
with Monad[LazyList]
with CoflatMap[LazyList]
with Align[LazyList] {

def empty[A]: LazyList[A] = LazyList.empty

Expand Down Expand Up @@ -134,19 +136,20 @@ trait LazyListInstances extends cats.kernel.instances.LazyListInstances {
alignWith(fa, fb)(identity)

override def alignWith[A, B, C](fa: LazyList[A], fb: LazyList[B])(f: Ior[A, B] => C): LazyList[C] = {
val iterA = fa.iterator
val iterB = fb.iterator

var result: LazyList[C] = LazyList.empty

while (iterA.hasNext || iterB.hasNext) {
val ior =
if (iterA.hasNext && iterB.hasNext) Ior.both(iterA.next(), iterB.next())
else if (iterA.hasNext) Ior.left(iterA.next())
else Ior.right(iterB.next())
result = result :+ f(ior)
val alignIterator = new Iterator[C] {
val iterA = fa.iterator
val iterB = fb.iterator
def hasNext: Boolean = iterA.hasNext || iterB.hasNext
def next(): C =
f(
if (iterA.hasNext && iterB.hasNext) Ior.both(iterA.next(), iterB.next())
else if (iterA.hasNext) Ior.left(iterA.next())
else Ior.right(iterB.next())
)
}
result

LazyList.from(alignIterator)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package tests

import cats.data.NonEmptyLazyList
import cats.kernel.laws.discipline.{EqTests, HashTests, OrderTests, PartialOrderTests, SemigroupTests}
import cats.laws.discipline.{AlignTests,BimonadTests, NonEmptyTraverseTests, SemigroupKTests, SerializableTests}
import cats.laws.discipline.{AlignTests, BimonadTests, NonEmptyTraverseTests, SemigroupKTests, SerializableTests}
import cats.laws.discipline.arbitrary._

class NonEmptyLazyListSuite extends CatsSuite {
Expand Down

0 comments on commit e249b96

Please sign in to comment.