From 5b4786b2b288d1d6942df63fd25adb939f423945 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Wed, 20 Jul 2016 09:40:19 -0400 Subject: [PATCH] Use traits to avoid code duplication in Nested instances --- core/src/main/scala/cats/data/Nested.scala | 246 +++++++++------------ 1 file changed, 110 insertions(+), 136 deletions(-) diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index e508983988..6675e5642a 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -32,201 +32,175 @@ private[data] sealed abstract class NestedInstances extends NestedInstances1 { FGA.on(_.value) implicit def catsDataTraverseForNested[F[_]: Traverse, G[_]: Traverse]: Traverse[Nested[F, G, ?]] = - new Traverse[Nested[F, G, ?]] { - val instance = Traverse[F].compose[G] - - def traverse[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[B]): H[Nested[F, G, B]] = - Applicative[H].map(instance.traverse(fga.value)(f))(Nested(_)) - - def foldLeft[A, B](fga: Nested[F, G, A], b: B)(f: (B, A) => B): B = - instance.foldLeft(fga.value, b)(f) - - def foldRight[A, B](fga: Nested[F, G, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - instance.foldRight(fga.value, lb)(f) - - override def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = - Nested(instance.map(fga.value)(f)) - - override def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) + new NestedTraverse[F, G] { + val FG: Traverse[λ[α => F[G[α]]]] = Traverse[F].compose[G] } } private[data] sealed abstract class NestedInstances1 extends NestedInstances2 { implicit def catsDataReducibleForNested[F[_]: Reducible, G[_]: Reducible]: Reducible[Nested[F, G, ?]] = - new Reducible[Nested[F, G, ?]] { - val instance = Reducible[F].compose[G] - - def reduceLeftTo[A, B](fga: Nested[F, G, A])(f: A => B)(g: (B, A) => B): B = - instance.reduceLeftTo(fga.value)(f)(g) - - def reduceRightTo[A, B](fga: Nested[F, G, A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = - instance.reduceRightTo(fga.value)(f)(g) - - def foldLeft[A, B](fga: Nested[F, G, A], b: B)(f: (B, A) => B): B = - instance.foldLeft(fga.value, b)(f) - - def foldRight[A, B](fga: Nested[F, G, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - instance.foldRight(fga.value, lb)(f) + new NestedReducible[F, G] { + val FG: Reducible[λ[α => F[G[α]]]] = Reducible[F].compose[G] } implicit def catsDataContravariantForNested[F[_]: Contravariant, G[_]: Contravariant]: Functor[Nested[F, G, ?]] = - new Functor[Nested[F, G, ?]] { - val instance = Contravariant[F].compose[G] - - def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = - Nested(instance.map(fga.value)(f)) + new NestedFunctor[F, G] { + val FG: Functor[λ[α => F[G[α]]]] = Contravariant[F].compose[G] } - } private[data] sealed abstract class NestedInstances2 extends NestedInstances3 { implicit def catsDataFoldableForNested[F[_]: Foldable, G[_]: Foldable]: Foldable[Nested[F, G, ?]] = - new Foldable[Nested[F, G, ?]] { - val instance = Foldable[F].compose[G] - - def foldLeft[A, B](fga: Nested[F, G, A], b: B)(f: (B, A) => B): B = - instance.foldLeft(fga.value, b)(f) - - def foldRight[A, B](fga: Nested[F, G, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - instance.foldRight(fga.value, lb)(f) + new NestedFoldable[F, G] { + val FG: Foldable[λ[α => F[G[α]]]] = Foldable[F].compose[G] } - implicit def catsDataContravariantForCovariantNested[F[_]: Contravariant, G[_]: Functor]: Contravariant[Nested[F, G, ?]] = - new Contravariant[Nested[F, G, ?]] { - val instance = Contravariant[F].composeFunctor[G] - - def contramap[A, B](fga: Nested[F, G, A])(f: B => A): Nested[F, G, B] = - Nested(instance.contramap(fga.value)(f)) + new NestedContravariant[F, G] { + val FG: Contravariant[λ[α => F[G[α]]]] = Contravariant[F].composeFunctor[G] } } private[data] sealed abstract class NestedInstances3 extends NestedInstances4 { implicit def catsDataAlternativeForNested[F[_]: Alternative, G[_]: Applicative]: Alternative[Nested[F, G, ?]] = - new Alternative[Nested[F, G, ?]] { - val instance = Alternative[F].compose[G] - - override def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) - - override def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = - Nested(instance.map(fga.value)(f)) - - def ap[A, B](fgf: Nested[F, G, A => B])(fga: Nested[F, G, A]): Nested[F, G, B] = - Nested(instance.ap(fgf.value)(fga.value)) - - override def product[A, B](fga: Nested[F, G, A], fgb: Nested[F, G, B]): Nested[F, G, (A, B)] = - Nested(instance.product(fga.value, fgb.value)) - - def pure[A](x: A): Nested[F, G, A] = Nested(instance.pure(x)) - - def combineK[A](x: Nested[F, G, A], y: Nested[F, G, A]): Nested[F, G, A] = Nested(instance.combineK(x.value, y.value)) - - def empty[A]: Nested[F, G, A] = Nested(instance.empty[A]) + new NestedAlternative[F, G] { + val FG: Alternative[λ[α => F[G[α]]]] = Alternative[F].compose[G] } implicit def catsDataContravariantForContravariantNested[F[_]: Functor, G[_]: Contravariant]: Contravariant[Nested[F, G, ?]] = - new Contravariant[Nested[F, G, ?]] { - val instance = Functor[F].composeContravariant[G] - - def contramap[A, B](fga: Nested[F, G, A])(f: B => A): Nested[F, G, B] = - Nested(instance.contramap(fga.value)(f)) + new NestedContravariant[F, G] { + val FG: Contravariant[λ[α => F[G[α]]]] = Functor[F].composeContravariant[G] } } private[data] sealed abstract class NestedInstances4 extends NestedInstances5 { implicit def catsDataApplicativeForNested[F[_]: Applicative, G[_]: Applicative]: Applicative[Nested[F, G, ?]] = - new Applicative[Nested[F, G, ?]] { - val instance = Applicative[F].compose[G] - - override def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) - - override def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = - Nested(instance.map(fga.value)(f)) - - def ap[A, B](fgf: Nested[F, G, A => B])(fga: Nested[F, G, A]): Nested[F, G, B] = - Nested(instance.ap(fgf.value)(fga.value)) - - override def product[A, B](fga: Nested[F, G, A], fgb: Nested[F, G, B]): Nested[F, G, (A, B)] = - Nested(instance.product(fga.value, fgb.value)) - - def pure[A](x: A): Nested[F, G, A] = Nested(instance.pure(x)) + new NestedApplicative[F, G] { + val FG: Applicative[λ[α => F[G[α]]]] = Applicative[F].compose[G] } implicit def catsDataMonoidKForNested[F[_]: MonoidK, G[_]]: MonoidK[Nested[F, G, ?]] = - new MonoidK[Nested[F, G, ?]] { - val instance = MonoidK[F].compose[G] - - def combineK[A](x: Nested[F, G, A], y: Nested[F, G, A]): Nested[F, G, A] = Nested(instance.combineK(x.value, y.value)) - - def empty[A]: Nested[F, G, A] = Nested(instance.empty[A]) + new NestedMonoidK[F, G] { + val FG: MonoidK[λ[α => F[G[α]]]] = MonoidK[F].compose[G] } } private[data] sealed abstract class NestedInstances5 extends NestedInstances6 { implicit def catsDataApplyForNested[F[_]: Apply, G[_]: Apply]: Apply[Nested[F, G, ?]] = - new Apply[Nested[F, G, ?]] { - val instance = Apply[F].compose[G] - - def ap[A, B](fgf: Nested[F, G, A => B])(fga: Nested[F, G, A]): Nested[F, G, B] = - Nested(instance.ap(fgf.value)(fga.value)) - - override def product[A, B](fga: Nested[F, G, A], fgb: Nested[F, G, B]): Nested[F, G, (A, B)] = - Nested(instance.product(fga.value, fgb.value)) - - def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = - Nested(instance.map(fga.value)(f)) + new NestedApply[F, G] { + val FG: Apply[λ[α => F[G[α]]]] = Apply[F].compose[G] } implicit def catsDataSemigroupKForNested[F[_]: SemigroupK, G[_]]: SemigroupK[Nested[F, G, ?]] = - new SemigroupK[Nested[F, G, ?]] { - val instance = SemigroupK[F].compose[G] - - def combineK[A](x: Nested[F, G, A], y: Nested[F, G, A]): Nested[F, G, A] = Nested(instance.combineK(x.value, y.value)) + new NestedSemigroupK[F, G] { + val FG: SemigroupK[λ[α => F[G[α]]]] = SemigroupK[F].compose[G] } } private[data] sealed abstract class NestedInstances6 extends NestedInstances7 { implicit def catsDataFunctorForNested[F[_]: Functor, G[_]: Functor]: Functor[Nested[F, G, ?]] = - new Functor[Nested[F, G, ?]] { - val instance = Functor[F].compose[G] - - def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = - Nested(instance.map(fga.value)(f)) - - override def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) + new NestedFunctor[F, G] { + val FG: Functor[λ[α => F[G[α]]]] = Functor[F].compose[G] } } private[data] sealed abstract class NestedInstances7 extends NestedInstances8 { implicit def catsDataInvariantForNested[F[_]: Invariant, G[_]: Invariant]: Invariant[Nested[F, G, ?]] = - new Invariant[Nested[F, G, ?]] { - val instance = Invariant[F].compose[G] - - def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) + new NestedInvariant[F, G] { + val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].compose[G] } } private[data] sealed abstract class NestedInstances8 extends NestedInstances9 { implicit def catsDataInvariantForCovariantNested[F[_]: Invariant, G[_]: Functor]: Invariant[Nested[F, G, ?]] = - new Invariant[Nested[F, G, ?]] { - val instance = Invariant[F].composeFunctor[G] - - def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) + new NestedInvariant[F, G] { + val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeFunctor[G] } } private[data] sealed abstract class NestedInstances9 { implicit def catsDataInvariantForNestedContravariant[F[_]: Invariant, G[_]: Contravariant]: Invariant[Nested[F, G, ?]] = - new Invariant[Nested[F, G, ?]] { - val instance = Invariant[F].composeContravariant[G] - - def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = - Nested(instance.imap(fga.value)(f)(g)) + new NestedInvariant[F, G] { + val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeContravariant[G] } } + +private[data] trait NestedInvariant[F[_], G[_]] extends Invariant[Nested[F, G, ?]] { + def FG: Invariant[λ[α => F[G[α]]]] + + override def imap[A, B](fga: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = + Nested(FG.imap(fga.value)(f)(g)) +} + +private[data] trait NestedFunctor[F[_], G[_]] extends Functor[Nested[F, G, ?]] with NestedInvariant[F, G] { + override def FG: Functor[λ[α => F[G[α]]]] + + override def map[A, B](fga: Nested[F, G, A])(f: A => B): Nested[F, G, B] = + Nested(FG.map(fga.value)(f)) +} + +private[data] trait NestedApply[F[_], G[_]] extends Apply[Nested[F, G, ?]] with NestedFunctor[F, G] { + override def FG: Apply[λ[α => F[G[α]]]] + + override def ap[A, B](fgf: Nested[F, G, A => B])(fga: Nested[F, G, A]): Nested[F, G, B] = + Nested(FG.ap(fgf.value)(fga.value)) + + override def product[A, B](fga: Nested[F, G, A], fgb: Nested[F, G, B]): Nested[F, G, (A, B)] = + Nested(FG.product(fga.value, fgb.value)) +} + +private[data] trait NestedApplicative[F[_], G[_]] extends Applicative[Nested[F, G, ?]] with NestedApply[F, G] { + def FG: Applicative[λ[α => F[G[α]]]] + + def pure[A](x: A): Nested[F, G, A] = Nested(FG.pure(x)) +} + +private[data] trait NestedSemigroupK[F[_], G[_]] extends SemigroupK[Nested[F, G, ?]] { + def FG: SemigroupK[λ[α => F[G[α]]]] + + def combineK[A](x: Nested[F, G, A], y: Nested[F, G, A]): Nested[F, G, A] = Nested(FG.combineK(x.value, y.value)) +} + +private[data] trait NestedMonoidK[F[_], G[_]] extends MonoidK[Nested[F, G, ?]] with NestedSemigroupK[F, G] { + def FG: MonoidK[λ[α => F[G[α]]]] + + def empty[A]: Nested[F, G, A] = Nested(FG.empty[A]) +} + +private[data] trait NestedAlternative[F[_], G[_]] extends Alternative[Nested[F, G, ?]] with NestedApplicative[F, G] with NestedMonoidK[F, G] { + def FG: Alternative[λ[α => F[G[α]]]] +} + +private[data] trait NestedFoldable[F[_], G[_]] extends Foldable[Nested[F, G, ?]] { + def FG: Foldable[λ[α => F[G[α]]]] + + def foldLeft[A, B](fga: Nested[F, G, A], b: B)(f: (B, A) => B): B = + FG.foldLeft(fga.value, b)(f) + + def foldRight[A, B](fga: Nested[F, G, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = + FG.foldRight(fga.value, lb)(f) +} + +private[data] trait NestedTraverse[F[_], G[_]] extends Traverse[Nested[F, G, ?]] with NestedFoldable[F, G] with NestedFunctor[F, G] { + def FG: Traverse[λ[α => F[G[α]]]] + + override def traverse[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[B]): H[Nested[F, G, B]] = + Applicative[H].map(FG.traverse(fga.value)(f))(Nested(_)) +} + +private[data] trait NestedReducible[F[_], G[_]] extends Reducible[Nested[F, G, ?]] with NestedFoldable[F, G] { + def FG: Reducible[λ[α => F[G[α]]]] + + def reduceLeftTo[A, B](fga: Nested[F, G, A])(f: A => B)(g: (B, A) => B): B = + FG.reduceLeftTo(fga.value)(f)(g) + + def reduceRightTo[A, B](fga: Nested[F, G, A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = + FG.reduceRightTo(fga.value)(f)(g) +} + +private[data] trait NestedContravariant[F[_], G[_]] extends Contravariant[Nested[F, G, ?]] { + def FG: Contravariant[λ[α => F[G[α]]]] + + def contramap[A, B](fga: Nested[F, G, A])(f: B => A): Nested[F, G, B] = + Nested(FG.contramap(fga.value)(f)) +}