diff --git a/alleycats-core/src/main/scala/alleycats/std/map.scala b/alleycats-core/src/main/scala/alleycats/std/map.scala index d98b669ed3..f26538da61 100644 --- a/alleycats-core/src/main/scala/alleycats/std/map.scala +++ b/alleycats-core/src/main/scala/alleycats/std/map.scala @@ -50,6 +50,8 @@ trait MapInstances { override def toList[A](fa: Map[K, A]): List[A] = fa.values.toList + override def toIterable[A](fa: Map[K, A]): Iterable[A] = fa.values + override def collectFirst[A, B](fa: Map[K, A])(pf: PartialFunction[A, B]): Option[B] = fa.collectFirst(new PartialFunction[(K, A), B] { override def isDefinedAt(x: (K, A)) = pf.isDefinedAt(x._2) diff --git a/alleycats-core/src/main/scala/alleycats/std/set.scala b/alleycats-core/src/main/scala/alleycats/std/set.scala index 3f763cd87a..af9747b75c 100644 --- a/alleycats-core/src/main/scala/alleycats/std/set.scala +++ b/alleycats-core/src/main/scala/alleycats/std/set.scala @@ -122,6 +122,8 @@ trait SetInstances { override def toList[A](fa: Set[A]): List[A] = fa.toList + override def toIterable[A](fa: Set[A]): Iterable[A] = fa + override def reduceLeftOption[A](fa: Set[A])(f: (A, A) => A): Option[A] = fa.reduceLeftOption(f) diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala index d7722fe918..31c155168e 100644 --- a/core/src/main/scala/cats/Composed.scala +++ b/core/src/main/scala/cats/Composed.scala @@ -73,6 +73,12 @@ private[cats] trait ComposedFoldable[F[_], G[_]] extends Foldable[λ[α => F[G[ override def foldRight[A, B](fga: F[G[A]], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = F.foldRight(fga, lb)((ga, lb) => G.foldRight(ga, lb)(f)) + + override def toList[A](fga: F[G[A]]): List[A] = + F.toList(fga).flatMap(G.toList) + + override def toIterable[A](fga: F[G[A]]): Iterable[A] = + F.toIterable(fga).flatMap(G.toIterable) } private[cats] trait ComposedTraverse[F[_], G[_]] diff --git a/core/src/main/scala/cats/Foldable.scala b/core/src/main/scala/cats/Foldable.scala index 9370e24913..7616bd7d76 100644 --- a/core/src/main/scala/cats/Foldable.scala +++ b/core/src/main/scala/cats/Foldable.scala @@ -337,11 +337,11 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s * res1: Option[String] = None * }}} */ - def collectFirstSome[A, B](fa: F[A])(f: A => Option[B]): Option[B] = - foldRight(fa, Eval.now(Option.empty[B])) { (a, lb) => - val ob = f(a) - if (ob.isDefined) Eval.now(ob) else lb - }.value + def collectFirstSome[A, B](fa: F[A])(f: A => Option[B]): Option[B] = { + val maybeEmpty = toIterable(fa).iterator.map(f).dropWhile(_.isEmpty) + if (maybeEmpty.hasNext) maybeEmpty.next() + else None + } /** * Monadic version of `collectFirstSome`. @@ -622,9 +622,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s * Find the first element matching the predicate, if one exists. */ def find[A](fa: F[A])(f: A => Boolean): Option[A] = - foldRight(fa, Now(Option.empty[A])) { (a, lb) => - if (f(a)) Now(Some(a)) else lb - }.value + toIterable(fa).find(f) /** * Find the first element matching the effectful predicate, if one exists. @@ -662,9 +660,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s * If there are no elements, the result is `false`. */ override def exists[A](fa: F[A])(p: A => Boolean): Boolean = - foldRight(fa, Eval.False) { (a, lb) => - if (p(a)) Eval.True else lb - }.value + toIterable(fa).exists(p) /** * Check whether all elements satisfy the predicate. @@ -672,9 +668,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s * If there are no elements, the result is `true`. */ override def forall[A](fa: F[A])(p: A => Boolean): Boolean = - foldRight(fa, Eval.True) { (a, lb) => - if (p(a)) lb else Eval.False - }.value + toIterable(fa).forall(p) /** * Check whether at least one element satisfies the effectful predicate. @@ -792,9 +786,7 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s * match `p`. */ def takeWhile_[A](fa: F[A])(p: A => Boolean): List[A] = - foldRight(fa, Now(List.empty[A])) { (a, llst) => - if (p(a)) llst.map(a :: _) else Now(Nil) - }.value + toIterable(fa).iterator.takeWhile(p).toList /** * Convert F[A] to a List[A], dropping all initial elements which diff --git a/core/src/main/scala/cats/data/NonEmptyList.scala b/core/src/main/scala/cats/data/NonEmptyList.scala index 26944c873e..62612e5f29 100644 --- a/core/src/main/scala/cats/data/NonEmptyList.scala +++ b/core/src/main/scala/cats/data/NonEmptyList.scala @@ -825,6 +825,8 @@ sealed abstract private[data] class NonEmptyListInstances extends NonEmptyListIn override def toList[A](fa: NonEmptyList[A]): List[A] = fa.toList + override def toIterable[A](fa: NonEmptyList[A]): Iterable[A] = fa.toList + override def toNonEmptyList[A](fa: NonEmptyList[A]): NonEmptyList[A] = fa override def get[A](fa: NonEmptyList[A])(idx: Long): Option[A] = diff --git a/core/src/main/scala/cats/data/NonEmptySeq.scala b/core/src/main/scala/cats/data/NonEmptySeq.scala index 482c7c189d..d15542d0d5 100644 --- a/core/src/main/scala/cats/data/NonEmptySeq.scala +++ b/core/src/main/scala/cats/data/NonEmptySeq.scala @@ -477,6 +477,8 @@ sealed abstract private[data] class NonEmptySeqInstances { override def toList[A](fa: NonEmptySeq[A]): List[A] = fa.toSeq.toList + override def toIterable[A](fa: NonEmptySeq[A]): Iterable[A] = fa.toSeq + override def toNonEmptyList[A](fa: NonEmptySeq[A]): NonEmptyList[A] = NonEmptyList(fa.head, fa.tail.toList) diff --git a/core/src/main/scala/cats/data/NonEmptySet.scala b/core/src/main/scala/cats/data/NonEmptySet.scala index c55cb34c78..0fc3328ebe 100644 --- a/core/src/main/scala/cats/data/NonEmptySet.scala +++ b/core/src/main/scala/cats/data/NonEmptySet.scala @@ -386,6 +386,8 @@ sealed abstract private[data] class NonEmptySetInstances extends NonEmptySetInst override def toList[A](fa: NonEmptySet[A]): List[A] = fa.toSortedSet.toList + override def toIterable[A](fa: NonEmptySet[A]): Iterable[A] = fa.toSortedSet + override def toNonEmptyList[A](fa: NonEmptySet[A]): NonEmptyList[A] = fa.toNonEmptyList } diff --git a/core/src/main/scala/cats/data/NonEmptyVector.scala b/core/src/main/scala/cats/data/NonEmptyVector.scala index cfd8d4c33f..bdc9e139e3 100644 --- a/core/src/main/scala/cats/data/NonEmptyVector.scala +++ b/core/src/main/scala/cats/data/NonEmptyVector.scala @@ -479,6 +479,8 @@ sealed abstract private[data] class NonEmptyVectorInstances { override def toList[A](fa: NonEmptyVector[A]): List[A] = fa.toVector.toList + override def toIterable[A](fa: NonEmptyVector[A]): Iterable[A] = fa.toVector + override def toNonEmptyList[A](fa: NonEmptyVector[A]): NonEmptyList[A] = NonEmptyList(fa.head, fa.tail.toList) diff --git a/core/src/main/scala/cats/instances/either.scala b/core/src/main/scala/cats/instances/either.scala index da03849ad9..8efa5ef581 100644 --- a/core/src/main/scala/cats/instances/either.scala +++ b/core/src/main/scala/cats/instances/either.scala @@ -151,7 +151,12 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances { fab.forall(p) override def toList[B](fab: Either[A, B]): List[B] = - fab.fold(_ => Nil, _ :: Nil) + fab match { + case Right(a) => a :: Nil + case Left(_) => Nil + } + + override def toIterable[B](fab: Either[A, B]): Iterable[B] = toList(fab) override def isEmpty[B](fab: Either[A, B]): Boolean = fab.isLeft diff --git a/core/src/main/scala/cats/instances/list.scala b/core/src/main/scala/cats/instances/list.scala index bcd852d06d..434a916d20 100644 --- a/core/src/main/scala/cats/instances/list.scala +++ b/core/src/main/scala/cats/instances/list.scala @@ -202,6 +202,8 @@ trait ListInstances extends cats.kernel.instances.ListInstances { override def toList[A](fa: List[A]): List[A] = fa + override def toIterable[A](fa: List[A]): Iterable[A] = fa + override def reduceLeftOption[A](fa: List[A])(f: (A, A) => A): Option[A] = fa.reduceLeftOption(f) diff --git a/core/src/main/scala/cats/instances/queue.scala b/core/src/main/scala/cats/instances/queue.scala index 4466f38293..df2b5d0940 100644 --- a/core/src/main/scala/cats/instances/queue.scala +++ b/core/src/main/scala/cats/instances/queue.scala @@ -131,6 +131,8 @@ trait QueueInstances extends cats.kernel.instances.QueueInstances { override def toList[A](fa: Queue[A]): List[A] = fa.toList + override def toIterable[A](fa: Queue[A]): Iterable[A] = fa + override def reduceLeftOption[A](fa: Queue[A])(f: (A, A) => A): Option[A] = fa.reduceLeftOption(f) diff --git a/core/src/main/scala/cats/instances/seq.scala b/core/src/main/scala/cats/instances/seq.scala index 0ba777eb44..b8e52d0309 100644 --- a/core/src/main/scala/cats/instances/seq.scala +++ b/core/src/main/scala/cats/instances/seq.scala @@ -117,6 +117,8 @@ trait SeqInstances extends cats.kernel.instances.SeqInstances { override def toList[A](fa: Seq[A]): List[A] = fa.toList + override def toIterable[A](fa: Seq[A]): Iterable[A] = fa + override def reduceLeftOption[A](fa: Seq[A])(f: (A, A) => A): Option[A] = fa.reduceLeftOption(f) diff --git a/core/src/main/scala/cats/instances/sortedMap.scala b/core/src/main/scala/cats/instances/sortedMap.scala index 73a8d84374..81caffbbda 100644 --- a/core/src/main/scala/cats/instances/sortedMap.scala +++ b/core/src/main/scala/cats/instances/sortedMap.scala @@ -114,6 +114,8 @@ trait SortedMapInstances extends SortedMapInstances2 { override def toList[A](fa: SortedMap[K, A]): List[A] = fa.values.toList + override def toIterable[A](fa: SortedMap[K, A]): Iterable[A] = fa.values + override def collectFirst[A, B](fa: SortedMap[K, A])(pf: PartialFunction[A, B]): Option[B] = fa.collectFirst(new PartialFunction[(K, A), B] { override def isDefinedAt(x: (K, A)): Boolean = pf.isDefinedAt(x._2) diff --git a/core/src/main/scala/cats/instances/sortedSet.scala b/core/src/main/scala/cats/instances/sortedSet.scala index 377ed5a4f8..54ed34ea07 100644 --- a/core/src/main/scala/cats/instances/sortedSet.scala +++ b/core/src/main/scala/cats/instances/sortedSet.scala @@ -48,6 +48,8 @@ trait SortedSetInstances extends SortedSetInstances1 { override def toList[A](fa: SortedSet[A]): List[A] = fa.toList + override def toIterable[A](fa: SortedSet[A]): Iterable[A] = fa + override def reduceLeftOption[A](fa: SortedSet[A])(f: (A, A) => A): Option[A] = fa.reduceLeftOption(f) diff --git a/core/src/main/scala/cats/instances/tuple.scala b/core/src/main/scala/cats/instances/tuple.scala index 6e0e945222..b74d9bbb1c 100644 --- a/core/src/main/scala/cats/instances/tuple.scala +++ b/core/src/main/scala/cats/instances/tuple.scala @@ -98,6 +98,10 @@ sealed private[instances] trait Tuple2Instances extends Tuple2Instances1 { override def size[A](fa: (X, A)): Long = 1L + override def toList[A](fa: (X, A)): List[A] = fa._2 :: Nil + + override def toIterable[A](fa: (X, A)): Iterable[A] = toList(fa) + override def get[A](fa: (X, A))(idx: Long): Option[A] = if (idx == 0L) Some(fa._2) else None diff --git a/core/src/main/scala/cats/instances/vector.scala b/core/src/main/scala/cats/instances/vector.scala index a9e53a9a0c..90e0a313b5 100644 --- a/core/src/main/scala/cats/instances/vector.scala +++ b/core/src/main/scala/cats/instances/vector.scala @@ -155,6 +155,8 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances { override def toList[A](fa: Vector[A]): List[A] = fa.toList + override def toIterable[A](fa: Vector[A]): Iterable[A] = fa + override def reduceLeftOption[A](fa: Vector[A])(f: (A, A) => A): Option[A] = fa.reduceLeftOption(f)