Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override Foldable methods #1532

Merged
merged 3 commits into from
Feb 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ import simulacrum.typeclass
def foldK[G[_], A](fga: F[G[A]])(implicit G: MonoidK[G]): G[A] =
fold(fga)(G.algebra)


/**
* Find the first element matching the predicate, if one exists.
*/
Expand Down
68 changes: 67 additions & 1 deletion core/src/main/scala/cats/Reducible.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ import simulacrum.typeclass
* Traverse `F[A]` using `Apply[G]`.
*
* `A` values will be mapped into `G[B]` and combined using
* `Applicative#map2`.
* `Apply#map2`.
*
* This method is similar to [[Foldable.traverse_]]. There are two
* main differences:
Expand Down Expand Up @@ -176,6 +176,16 @@ import simulacrum.typeclass
case NonEmptyList(hd, tl) =>
Reducible[NonEmptyList].reduce(NonEmptyList(hd, a :: intersperseList(tl, a)))
}

override def isEmpty[A](fa: F[A]): Boolean = false

override def nonEmpty[A](fa: F[A]): Boolean = true

override def minimumOption[A](fa: F[A])(implicit A: Order[A]): Option[A] =
Some(minimum(fa))

override def maximumOption[A](fa: F[A])(implicit A: Order[A]): Option[A] =
Some(maximum(fa))
}

/**
Expand Down Expand Up @@ -210,4 +220,60 @@ abstract class NonEmptyReducible[F[_], G[_]](implicit G: Foldable[G]) extends Re
case None => Later(f(a))
}
}

override def size[A](fa: F[A]): Long = {
val (_, tail) = split(fa)
1 + G.size(tail)
}

override def fold[A](fa: F[A])(implicit A: Monoid[A]): A = {
val (a, ga) = split(fa)
A.combine(a, G.fold(ga))
}

override def foldM[H[_], A, B](fa: F[A], z: B)(f: (B, A) => H[B])(implicit H: Monad[H]): H[B] = {
val (a, ga) = split(fa)
H.flatMap(f(z, a))(G.foldM(ga, _)(f))
}

override def find[A](fa: F[A])(f: A => Boolean): Option[A] = {
val (a, ga) = split(fa)
if (f(a)) Some(a) else G.find(ga)(f)
}

override def exists[A](fa: F[A])(p: A => Boolean): Boolean = {
val (a, ga) = split(fa)
p(a) || G.exists(ga)(p)
}

override def forall[A](fa: F[A])(p: A => Boolean): Boolean = {
val (a, ga) = split(fa)
p(a) && G.forall(ga)(p)
}

override def toList[A](fa: F[A]): List[A] = {
val (a, ga) = split(fa)
a :: G.toList(ga)
}

override def toNonEmptyList[A](fa: F[A]): NonEmptyList[A] = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method code path is untested

val (a, ga) = split(fa)
NonEmptyList(a, G.toList(ga))
}

override def filter_[A](fa: F[A])(p: A => Boolean): List[A] = {
val (a, ga) = split(fa)
val filteredTail = G.filter_(ga)(p)
if (p(a)) a :: filteredTail else filteredTail
}

override def takeWhile_[A](fa: F[A])(p: A => Boolean): List[A] = {
val (a, ga) = split(fa)
if (p(a)) a :: G.takeWhile_(ga)(p) else Nil
}

override def dropWhile_[A](fa: F[A])(p: A => Boolean): List[A] = {
val (a, ga) = split(fa)
if (p(a)) G.dropWhile_(ga)(p) else a :: G.toList(ga)
}
}
9 changes: 9 additions & 0 deletions core/src/main/scala/cats/data/NonEmptyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,15 @@ private[data] sealed trait NonEmptyListInstances extends NonEmptyListInstances0
NonEmptyList.fromListUnsafe(buf.result())
}

override def fold[A](fa: NonEmptyList[A])(implicit A: Monoid[A]): A =
fa.reduce

override def foldM[G[_], A, B](fa: NonEmptyList[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] =
Foldable.iteratorFoldM(fa.toList.toIterator, z)(f)

override def find[A](fa: NonEmptyList[A])(f: A => Boolean): Option[A] =
fa find f

override def forall[A](fa: NonEmptyList[A])(p: A => Boolean): Boolean =
fa forall p

Expand Down
16 changes: 15 additions & 1 deletion core/src/main/scala/cats/data/NonEmptyVector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ private[data] sealed trait NonEmptyVectorInstances {
def traverse[G[_], A, B](fa: NonEmptyVector[A])(f: (A) => G[B])(implicit G: Applicative[G]): G[NonEmptyVector[B]] =
G.map2Eval(f(fa.head), Always(Traverse[Vector].traverse(fa.tail)(f)))(NonEmptyVector(_, _)).value


override def foldLeft[A, B](fa: NonEmptyVector[A], b: B)(f: (B, A) => B): B =
fa.foldLeft(b)(f)

Expand All @@ -251,6 +250,21 @@ private[data] sealed trait NonEmptyVectorInstances {
NonEmptyVector.fromVectorUnsafe(buf.result())
}

override def fold[A](fa: NonEmptyVector[A])(implicit A: Monoid[A]): A =
fa.reduce

override def foldM[G[_], A, B](fa: NonEmptyVector[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] =
Foldable.iteratorFoldM(fa.toVector.toIterator, z)(f)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code path is untested.


override def find[A](fa: NonEmptyVector[A])(f: A => Boolean): Option[A] =
fa.find(f)

override def forall[A](fa: NonEmptyVector[A])(p: A => Boolean): Boolean =
fa.forall(p)

override def exists[A](fa: NonEmptyVector[A])(p: A => Boolean): Boolean =
fa.exists(p)

override def toList[A](fa: NonEmptyVector[A]): List[A] = fa.toVector.toList

override def toNonEmptyList[A](fa: NonEmptyVector[A]): NonEmptyList[A] =
Expand Down
34 changes: 34 additions & 0 deletions core/src/main/scala/cats/data/Validated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ private[data] sealed abstract class ValidatedInstances extends ValidatedInstance
fab.leftMap(f)
}

// scalastyle:off method.length
implicit def catsDataInstancesForValidated[E](implicit E: Semigroup[E]): Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] =
new Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] {
def traverse[F[_]: Applicative, A, B](fa: Validated[E, A])(f: A => F[B]): F[Validated[E, B]] =
Expand Down Expand Up @@ -323,7 +324,40 @@ private[data] sealed abstract class ValidatedInstances extends ValidatedInstance
case v @ Validated.Valid(_) => v
}
def raiseError[A](e: E): Validated[E, A] = Validated.Invalid(e)

override def reduceLeftToOption[A, B](fa: Validated[E, A])(f: A => B)(g: (B, A) => B): Option[B] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next 5 methods untested.

fa.map(f).toOption

override def reduceRightToOption[A, B](fa: Validated[E, A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] =
Now(fa.map(f).toOption)

override def reduceLeftOption[A](fa: Validated[E, A])(f: (A, A) => A): Option[A] =
fa.toOption

override def reduceRightOption[A](fa: Validated[E, A])(f: (A, Eval[A]) => Eval[A]): Eval[Option[A]] =
Now(fa.toOption)

override def size[A](fa: Validated[E, A]): Long =
fa.fold(_ => 0L, _ => 1L)

override def foldMap[A, B](fa: Validated[E, A])(f: A => B)(implicit B: Monoid[B]): B =
fa.fold(_ => B.empty, f)

override def find[A](fa: Validated[E, A])(f: A => Boolean): Option[A] =
fa.toOption.filter(f)

override def exists[A](fa: Validated[E, A])(p: A => Boolean): Boolean =
fa.exists(p)

override def forall[A](fa: Validated[E, A])(p: A => Boolean): Boolean =
fa.forall(p)

override def toList[A](fa: Validated[E, A]): List[A] =
fa.fold(_ => Nil, _ :: Nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

untested


override def isEmpty[A](fa: Validated[E, A]): Boolean = fa.isInvalid
}
// scalastyle:on method.length
}

private[data] sealed abstract class ValidatedInstances1 extends ValidatedInstances2 {
Expand Down
36 changes: 36 additions & 0 deletions core/src/main/scala/cats/instances/either.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,48 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances {

override def attempt[B](fab: Either[A, B]): Either[A, Either[A, B]] =
Right(fab)

override def recover[B](fab: Either[A, B])(pf: PartialFunction[A, B]): Either[A, B] =
fab recover pf

override def recoverWith[B](fab: Either[A, B])(pf: PartialFunction[A, Either[A, B]]): Either[A, B] =
fab recoverWith pf

override def ensure[B](fab: Either[A, B])(error: => A)(predicate: B => Boolean): Either[A, B] =
fab.ensure(error)(predicate)

override def reduceLeftToOption[B, C](fab: Either[A, B])(f: B => C)(g: (C, B) => C): Option[C] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next 5 method untested.

fab.right.map(f).toOption

override def reduceRightToOption[B, C](fab: Either[A, B])(f: B => C)(g: (B, Eval[C]) => Eval[C]): Eval[Option[C]] =
Now(fab.right.map(f).toOption)

override def reduceLeftOption[B](fab: Either[A, B])(f: (B, B) => B): Option[B] =
fab.right.toOption

override def reduceRightOption[B](fab: Either[A, B])(f: (B, Eval[B]) => Eval[B]): Eval[Option[B]] =
Now(fab.right.toOption)

override def size[B](fab: Either[A, B]): Long =
fab.fold(_ => 0L, _ => 1L)

override def foldMap[B, C](fab: Either[A, B])(f: B => C)(implicit C: Monoid[C]): C =
fab.fold(_ => C.empty, f)

override def find[B](fab: Either[A, B])(f: B => Boolean): Option[B] =
fab.fold(_ => None, r => if (f(r)) Some(r) else None)

override def exists[B](fab: Either[A, B])(p: B => Boolean): Boolean =
fab.right.exists(p)

override def forall[B](fab: Either[A, B])(p: B => Boolean): Boolean =
fab.right.forall(p)

override def toList[B](fab: Either[A, B]): List[B] =
fab.fold(_ => Nil, _ :: Nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

untested.


override def isEmpty[B](fab: Either[A, B]): Boolean =
fab.isLeft
}
// scalastyle:on method.length

Expand Down
13 changes: 13 additions & 0 deletions core/src/main/scala/cats/instances/list.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ trait ListInstances extends cats.kernel.instances.ListInstances {
override def fold[A](fa: List[A])(implicit A: Monoid[A]): A = A.combineAll(fa)

override def toList[A](fa: List[A]): List[A] = fa

override def reduceLeftOption[A](fa: List[A])(f: (A, A) => A): Option[A] =
fa.reduceLeftOption(f)

override def find[A](fa: List[A])(f: A => Boolean): Option[A] = fa.find(f)

override def filter_[A](fa: List[A])(p: A => Boolean): List[A] = fa.filter(p)

override def takeWhile_[A](fa: List[A])(p: A => Boolean): List[A] = fa.takeWhile(p)

override def dropWhile_[A](fa: List[A])(p: A => Boolean): List[A] = fa.dropWhile(p)

override def algebra[A]: Monoid[List[A]] = new kernel.instances.ListMonoid[A]
}

implicit def catsStdShowForList[A:Show]: Show[List[A]] =
Expand Down
34 changes: 34 additions & 0 deletions core/src/main/scala/cats/instances/option.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,46 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances {
override def filter[A](fa: Option[A])(p: A => Boolean): Option[A] =
fa.filter(p)

override def reduceLeftToOption[A, B](fa: Option[A])(f: A => B)(g: (B, A) => B): Option[B] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next 5 methods untested.

fa.map(f)

override def reduceRightToOption[A, B](fa: Option[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] =
Now(fa.map(f))

override def reduceLeftOption[A](fa: Option[A])(f: (A, A) => A): Option[A] = fa

override def reduceRightOption[A](fa: Option[A])(f: (A, Eval[A]) => Eval[A]): Eval[Option[A]] =
Now(fa)

override def minimumOption[A](fa: Option[A])(implicit A: Order[A]): Option[A] = fa

override def maximumOption[A](fa: Option[A])(implicit A: Order[A]): Option[A] = fa

override def size[A](fa: Option[A]): Long = fa.fold(0L)(_ => 1L)

override def foldMap[A, B](fa: Option[A])(f: A => B)(implicit B: Monoid[B]): B =
fa.fold(B.empty)(f)

override def find[A](fa: Option[A])(f: A => Boolean): Option[A] =
fa.filter(f)

override def exists[A](fa: Option[A])(p: A => Boolean): Boolean =
fa.exists(p)

override def forall[A](fa: Option[A])(p: A => Boolean): Boolean =
fa.forall(p)

override def toList[A](fa: Option[A]): List[A] = fa.toList

override def filter_[A](fa: Option[A])(p: A => Boolean): List[A] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next 5 methods untested.

fa.filter(p).toList

override def takeWhile_[A](fa: Option[A])(p: A => Boolean): List[A] =
fa.filter(p).toList

override def dropWhile_[A](fa: Option[A])(p: A => Boolean): List[A] =
fa.filterNot(p).toList

override def isEmpty[A](fa: Option[A]): Boolean =
fa.isEmpty
}
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/scala/cats/instances/set.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ trait SetInstances extends cats.kernel.instances.SetInstances {
override def fold[A](fa: Set[A])(implicit A: Monoid[A]): A = A.combineAll(fa)

override def toList[A](fa: Set[A]): List[A] = fa.toList

override def reduceLeftOption[A](fa: Set[A])(f: (A, A) => A): Option[A] =
fa.reduceLeftOption(f)

override def find[A](fa: Set[A])(f: A => Boolean): Option[A] = fa.find(f)
}

implicit def catsStdShowForSet[A:Show]: Show[Set[A]] = new Show[Set[A]] {
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/scala/cats/instances/stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
override def fold[A](fa: Stream[A])(implicit A: Monoid[A]): A = A.combineAll(fa)

override def toList[A](fa: Stream[A]): List[A] = fa.toList

override def reduceLeftOption[A](fa: Stream[A])(f: (A, A) => A): Option[A] =
fa.reduceLeftOption(f)

override def find[A](fa: Stream[A])(f: A => Boolean): Option[A] = fa.find(f)

override def algebra[A]: Monoid[Stream[A]] = new kernel.instances.StreamMonoid[A]
}

implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] =
Expand Down
48 changes: 48 additions & 0 deletions core/src/main/scala/cats/instances/try.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ trait TryInstances extends TryInstances1 {
ta.recoverWith { case t => f(t) }

def raiseError[A](e: Throwable): Try[A] = Failure(e)

override def handleError[A](ta: Try[A])(f: Throwable => A): Try[A] =
ta.recover { case t => f(t) }

Expand All @@ -75,6 +76,53 @@ trait TryInstances extends TryInstances1 {
override def recoverWith[A](ta: Try[A])(pf: PartialFunction[Throwable, Try[A]]): Try[A] = ta.recoverWith(pf)

override def map[A, B](ta: Try[A])(f: A => B): Try[B] = ta.map(f)

override def reduceLeftToOption[A, B](fa: Try[A])(f: A => B)(g: (B, A) => B): Option[B] =
fa.map(f).toOption

override def reduceRightToOption[A, B](fa: Try[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] =
Now(fa.map(f).toOption)

override def reduceLeftOption[A](fa: Try[A])(f: (A, A) => A): Option[A] =
fa.toOption

override def reduceRightOption[A](fa: Try[A])(f: (A, Eval[A]) => Eval[A]): Eval[Option[A]] =
Now(fa.toOption)

override def size[A](fa: Try[A]): Long =
fa match {
case Failure(_) => 0L
case Success(_) => 1L
}

override def find[A](fa: Try[A])(f: A => Boolean): Option[A] =
fa.toOption.filter(f)

override def foldMap[A, B](fa: Try[A])(f: A => B)(implicit B: Monoid[B]): B =
fa match {
case Failure(_) => B.empty
case Success(a) => f(a)
}

override def exists[A](fa: Try[A])(p: A => Boolean): Boolean =
fa match {
case Failure(_) => false
case Success(a) => p(a)
}

override def forall[A](fa: Try[A])(p: A => Boolean): Boolean =
fa match {
case Failure(_) => true
case Success(a) => p(a)
}

override def toList[A](fa: Try[A]): List[A] =
fa match {
case Failure(_) => Nil
case Success(a) => a :: Nil
}

override def isEmpty[A](fa: Try[A]): Boolean = fa.isFailure
}
// scalastyle:on method.length

Expand Down
Loading