From 8b91042fa77de7673985b168e909649623047e47 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 12:10:15 -0700 Subject: [PATCH 01/12] Workaround for ambiguous implicits when using MTL type classes, fixes #1210 --- core/src/main/scala/cats/MonadReader.scala | 4 +++- core/src/main/scala/cats/data/Kleisli.scala | 20 ++++++++++++------- .../main/scala/cats/instances/function.scala | 6 ++++-- .../scala/cats/laws/MonadReaderLaws.scala | 15 +++++++------- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/core/src/main/scala/cats/MonadReader.scala b/core/src/main/scala/cats/MonadReader.scala index 5614ced482..a1eb9637db 100644 --- a/core/src/main/scala/cats/MonadReader.scala +++ b/core/src/main/scala/cats/MonadReader.scala @@ -1,7 +1,9 @@ package cats /** A monad that has the ability to read from an environment. */ -trait MonadReader[F[_], R] extends Monad[F] { +trait MonadReader[F[_], R] { + def monad: Monad[F] + /** Get the environment */ def ask: F[R] diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 0d7552997f..068d812eb8 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -81,7 +81,6 @@ private[data] sealed trait KleisliFunctions { } private[data] sealed abstract class KleisliInstances extends KleisliInstances0 { - implicit def catsDataMonoidForKleisli[F[_], A, B](implicit M: Monoid[F[B]]): Monoid[Kleisli[F, A, B]] = new KleisliMonoid[F, A, B] { def FB: Monoid[F[B]] = M } @@ -114,6 +113,9 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 { implicit def catsDataMonadReaderForKleisliId[A]: MonadReader[Kleisli[Id, A, ?], A] = catsDataMonadReaderForKleisli[Id, A] + implicit def catsDataMonadForKleisliId[A]: Monad[Kleisli[Id, A, ?]] = + catsDataMonadForKleisli[Id, A] + implicit def catsDataContravariantForKleisli[F[_], C]: Contravariant[Kleisli[F, ?, C]] = new Contravariant[Kleisli[F, ?, C]] { override def contramap[A, B](fa: Kleisli[F, A, C])(f: (B) => A): Kleisli[F, B, C] = @@ -187,19 +189,23 @@ private[data] sealed abstract class KleisliInstances3 extends KleisliInstances4 } private[data] sealed abstract class KleisliInstances4 { - implicit def catsDataMonadReaderForKleisli[F[_]: Monad, A]: MonadReader[Kleisli[F, A, ?], A] = new MonadReader[Kleisli[F, A, ?], A] { - def pure[B](x: B): Kleisli[F, A, B] = - Kleisli.pure[F, A, B](x) - - def flatMap[B, C](fa: Kleisli[F, A, B])(f: B => Kleisli[F, A, C]): Kleisli[F, A, C] = - fa.flatMap(f) + val monad = catsDataMonadForKleisli[F, A] val ask: Kleisli[F, A, A] = Kleisli(Monad[F].pure) def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = Kleisli(f.andThen(fa.run)) + } + + implicit def catsDataMonadForKleisli[F[_]: Monad, A]: Monad[Kleisli[F, A, ?]] = + new Monad[Kleisli[F, A, ?]] { + def pure[B](x: B): Kleisli[F, A, B] = + Kleisli.pure[F, A, B](x) + + def flatMap[B, C](fa: Kleisli[F, A, B])(f: B => Kleisli[F, A, C]): Kleisli[F, A, C] = + fa.flatMap(f) def tailRecM[B, C](b: B)(f: B => Kleisli[F, A, Either[B, C]]): Kleisli[F, A, C] = Kleisli[F, A, C]({ a => FlatMap[F].tailRecM(b) { f(_).run(a) } }) diff --git a/core/src/main/scala/cats/instances/function.scala b/core/src/main/scala/cats/instances/function.scala index 13fe53733e..14d3ba1248 100644 --- a/core/src/main/scala/cats/instances/function.scala +++ b/core/src/main/scala/cats/instances/function.scala @@ -42,8 +42,10 @@ private[instances] sealed trait Function1Instances { fa.compose(f) } - implicit def catsStdMonadReaderForFunction1[T1]: MonadReader[T1 => ?, T1] with RecursiveTailRecM[T1 => ?] = - new MonadReader[T1 => ?, T1] with RecursiveTailRecM[T1 => ?] { + implicit def catsStdMonadReaderForFunction1[T1]: MonadReader[T1 => ?, T1] with Monad[T1 => ?] with RecursiveTailRecM[T1 => ?] = + new MonadReader[T1 => ?, T1] with Monad[T1 => ?] with RecursiveTailRecM[T1 => ?] { + val monad = this + def pure[R](r: R): T1 => R = _ => r def flatMap[R1, R2](fa: T1 => R1)(f: R1 => T1 => R2): T1 => R2 = diff --git a/laws/src/main/scala/cats/laws/MonadReaderLaws.scala b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala index d72421cf32..2e96be2569 100644 --- a/laws/src/main/scala/cats/laws/MonadReaderLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala @@ -3,22 +3,23 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Reader/Class/index.html trait MonadReaderLaws[F[_], R] extends MonadLaws[F] { - implicit override def F: MonadReader[F, R] + implicit def FR: MonadReader[F, R] + implicit def F = FR.monad val monadReaderAskIdempotent: IsEq[F[R]] = - F.flatMap(F.ask)(_ => F.ask) <-> F.ask + F.flatMap(FR.ask)(_ => FR.ask) <-> FR.ask def monadReaderLocalAsk(f: R => R): IsEq[F[R]] = - F.local(f)(F.ask) <-> F.map(F.ask)(f) + FR.local(f)(FR.ask) <-> F.map(FR.ask)(f) def monadReaderLocalPure[A](a: A, f: R => R): IsEq[F[A]] = - F.local(f)(F.pure(a)) <-> F.pure(a) + FR.local(f)(F.pure(a)) <-> F.pure(a) def monadReaderLocalFlatMap[A, B](fra: F[A], f: A => F[B], g: R => R): IsEq[F[B]] = - F.local(g)(F.flatMap(fra)(f)) <-> F.flatMap(F.local(g)(fra))(a => F.local(g)(f(a))) + FR.local(g)(F.flatMap(fra)(f)) <-> F.flatMap(FR.local(g)(fra))(a => FR.local(g)(f(a))) } object MonadReaderLaws { - def apply[F[_], R](implicit FR: MonadReader[F, R]): MonadReaderLaws[F, R] = - new MonadReaderLaws[F, R] { def F: MonadReader[F, R] = FR } + def apply[F[_], R](implicit FR0: MonadReader[F, R]): MonadReaderLaws[F, R] = + new MonadReaderLaws[F, R] { def FR: MonadReader[F, R] = FR0 } } From a3712fd5361cd4e550c71f74bb6ee5d89d2fdc9f Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 12:29:49 -0700 Subject: [PATCH 02/12] Ambiguous implicits fix for MonadState --- core/src/main/scala/cats/MonadState.scala | 8 ++++--- core/src/main/scala/cats/data/StateT.scala | 6 ++++- free/src/main/scala/cats/free/FreeT.scala | 22 +++++++++---------- .../main/scala/cats/laws/MonadStateLaws.scala | 15 +++++++------ 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/core/src/main/scala/cats/MonadState.scala b/core/src/main/scala/cats/MonadState.scala index 4539971d5f..777314ef2e 100644 --- a/core/src/main/scala/cats/MonadState.scala +++ b/core/src/main/scala/cats/MonadState.scala @@ -16,14 +16,16 @@ package cats * } yield r * }}} */ -trait MonadState[F[_], S] extends Monad[F] { +trait MonadState[F[_], S] { + def monad: Monad[F] + def get: F[S] def set(s: S): F[Unit] - def modify(f: S => S): F[Unit] = flatMap(get)(s => set(f(s))) + def modify(f: S => S): F[Unit] = monad.flatMap(get)(s => set(f(s))) - def inspect[A](f: S => A): F[A] = map(get)(f) + def inspect[A](f: S => A): F[A] = monad.map(get)(f) } object MonadState { diff --git a/core/src/main/scala/cats/data/StateT.scala b/core/src/main/scala/cats/data/StateT.scala index 75b0c10401..db0ae87cc5 100644 --- a/core/src/main/scala/cats/data/StateT.scala +++ b/core/src/main/scala/cats/data/StateT.scala @@ -225,7 +225,11 @@ private[data] sealed trait StateTMonad[F[_], S] extends Monad[StateT[F, S, ?]] { }) } -private[data] sealed trait StateTMonadState[F[_], S] extends MonadState[StateT[F, S, ?], S] with StateTMonad[F, S] { +private[data] sealed trait StateTMonadState[F[_], S] extends MonadState[StateT[F, S, ?], S] { outer => + implicit def F: Monad[F] + + def monad = new StateTMonad[F, S] { implicit def F = outer.F } + lazy val get: StateT[F, S, S] = StateT(s => F.pure((s, s))) def set(s: S): StateT[F, S, Unit] = StateT(_ => F.pure((s, ()))) diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala index 28c114a9ee..b7e0578389 100644 --- a/free/src/main/scala/cats/free/FreeT.scala +++ b/free/src/main/scala/cats/free/FreeT.scala @@ -172,18 +172,7 @@ object FreeT extends FreeTInstances { } -private[free] sealed trait FreeTInstances3 { - implicit def catsFreeMonadStateForFreeT[S[_], M[_], E](implicit M1: MonadState[M, E]): MonadState[FreeT[S, M, ?], E] = - new MonadState[FreeT[S, M, ?], E] with FreeTMonad[S, M] { - override def M = implicitly - override def get = - FreeT.liftT(M1.get) - override def set(s: E) = - FreeT.liftT(M1.set(s)) - } -} - -private[free] sealed trait FreeTInstances2 extends FreeTInstances3 { +private[free] sealed trait FreeTInstances2 { implicit def catsFreeMonadErrorForFreeT[S[_], M[_]: RecursiveTailRecM, E](implicit E: MonadError[M, E]): MonadError[FreeT[S, M, ?], E] = new MonadError[FreeT[S, M, ?], E] with FreeTMonad[S, M] { override def M = implicitly @@ -224,6 +213,15 @@ private[free] sealed trait FreeTInstances0 extends FreeTInstances1 { } private[free] sealed trait FreeTInstances extends FreeTInstances0 { + implicit def catsFreeMonadStateForFreeT[S[_], M[_], E](implicit M1: MonadState[M, E]): MonadState[FreeT[S, M, ?], E] = + new MonadState[FreeT[S, M, ?], E] { + val monad = catsFreeMonadForFreeT[S, M](M1.monad) + override def get = + FreeT.liftT(M1.get)(M1.monad) + override def set(s: E) = + FreeT.liftT(M1.set(s))(M1.monad) + } + implicit def catsFreeMonadCombineForFreeT[S[_], M[_]: Alternative]: MonadCombine[FreeT[S, M, ?]] = new MonadCombine[FreeT[S, M, ?]] with FreeTCombine[S, M] with FreeTMonad[S, M] { override def M = implicitly diff --git a/laws/src/main/scala/cats/laws/MonadStateLaws.scala b/laws/src/main/scala/cats/laws/MonadStateLaws.scala index 99eac2080a..4eb7ebe5b4 100644 --- a/laws/src/main/scala/cats/laws/MonadStateLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadStateLaws.scala @@ -3,22 +3,23 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/State/Class/index.html trait MonadStateLaws[F[_], S] extends MonadLaws[F] { - implicit override def F: MonadState[F, S] + implicit def FS: MonadState[F, S] + implicit def F = FS.monad val monadStateGetIdempotent: IsEq[F[S]] = - F.flatMap(F.get)(_ => F.get) <-> F.get + F.flatMap(FS.get)(_ => FS.get) <-> FS.get def monadStateSetTwice(s: S, t: S): IsEq[F[Unit]] = - F.flatMap(F.set(s))(_ => F.set(t)) <-> F.set(t) + F.flatMap(FS.set(s))(_ => FS.set(t)) <-> FS.set(t) def monadStateSetGet(s: S): IsEq[F[S]] = - F.flatMap(F.set(s))(_ => F.get) <-> F.flatMap(F.set(s))(_ => F.pure(s)) + F.flatMap(FS.set(s))(_ => FS.get) <-> F.flatMap(FS.set(s))(_ => F.pure(s)) val monadStateGetSet: IsEq[F[Unit]] = - F.flatMap(F.get)(F.set) <-> F.pure(()) + F.flatMap(FS.get)(FS.set) <-> F.pure(()) } object MonadStateLaws { - def apply[F[_], S](implicit FS: MonadState[F, S]): MonadStateLaws[F, S] = - new MonadStateLaws[F, S] { def F: MonadState[F, S] = FS } + def apply[F[_], S](implicit FS0: MonadState[F, S]): MonadStateLaws[F, S] = + new MonadStateLaws[F, S] { def FS: MonadState[F, S] = FS0 } } From 1d70b819be0666edeec1216f907009abcdf63985 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 12:37:44 -0700 Subject: [PATCH 03/12] Ambiguous implicits fix for MonadWriter --- core/src/main/scala/cats/MonadWriter.scala | 8 ++++--- core/src/main/scala/cats/data/WriterT.scala | 22 ++++++++++++++++--- .../scala/cats/laws/MonadWriterLaws.scala | 15 +++++++------ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/core/src/main/scala/cats/MonadWriter.scala b/core/src/main/scala/cats/MonadWriter.scala index 5481e4cb96..268104e92f 100644 --- a/core/src/main/scala/cats/MonadWriter.scala +++ b/core/src/main/scala/cats/MonadWriter.scala @@ -1,7 +1,9 @@ package cats /** A monad that support monoidal accumulation (e.g. logging List[String]) */ -trait MonadWriter[F[_], W] extends Monad[F] { +trait MonadWriter[F[_], W] { + def monad: Monad[F] + /** Lift a writer action into the effect */ def writer[A](aw: (W, A)): F[A] @@ -16,11 +18,11 @@ trait MonadWriter[F[_], W] extends Monad[F] { /** Pair the value with an inspection of the accumulator */ def listens[A, B](fa: F[A])(f: W => B): F[(B, A)] = - map(listen(fa)) { case (w, a) => (f(w), a) } + monad.map(listen(fa)) { case (w, a) => (f(w), a) } /** Modify the accumulator */ def censor[A](fa: F[A])(f: W => W): F[A] = - flatMap(listen(fa)) { case (w, a) => writer((f(w), a)) } + monad.flatMap(listen(fa)) { case (w, a) => writer((f(w), a)) } } object MonadWriter { diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 9c85d97f52..98d48011a7 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -66,10 +66,12 @@ object WriterT extends WriterTInstances with WriterTFunctions { } private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { - - implicit def catsDataMonadForWriterTId[L:Monoid]: Monad[WriterT[Id, L, ?]] = + implicit def catsDataMonadWriterForWriterTId[L: Monoid]: MonadWriter[WriterT[Id, L, ?], L] = catsDataMonadWriterForWriterT[Id, L] + implicit def catsDataMonadForWriterTId[L: Monoid]: Monad[WriterT[Id, L, ?]] = + catsDataMonadForWriterT[Id, L] + implicit def catsDataEqForWriterTId[L: Eq, V: Eq]: Eq[WriterT[Id, L, V]] = catsDataEqForWriterT[Id, L, V] @@ -138,6 +140,12 @@ private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 implicit val L0: Monoid[L] = L } + implicit def catsDataMonadForWriterT[F[_], L](implicit F: Monad[F], L: Monoid[L]): Monad[WriterT[F, L, ?]] = + new WriterTMonad[F, L] { + implicit val F0: Monad[F] = F + implicit val L0: Monoid[L] = L + } + implicit def catsDataSemigroupForWriterT[F[_], L, V](implicit W: Semigroup[F[(L, V)]]): Semigroup[WriterT[F, L, V]] = new WriterTSemigroup[F, L, V] { implicit val F0: Semigroup[F[(L, V)]] = W @@ -329,7 +337,15 @@ private[data] sealed trait WriterTMonadError[F[_], L, E] extends MonadError[Writ override implicit def F0: MonadError[F, E] } -private[data] sealed trait WriterTMonadWriter[F[_], L] extends MonadWriter[WriterT[F, L, ?], L] with WriterTMonad[F, L] { +private[data] sealed trait WriterTMonadWriter[F[_], L] extends MonadWriter[WriterT[F, L, ?], L] { outer => + implicit def F0: Monad[F] + implicit def L0: Monoid[L] + + def monad = new WriterTMonad[F, L] { + implicit def F0 = outer.F0 + implicit def L0 = outer.L0 + } + def writer[A](aw: (L, A)): WriterT[F, L, A] = WriterT.put(aw._2)(aw._1) diff --git a/laws/src/main/scala/cats/laws/MonadWriterLaws.scala b/laws/src/main/scala/cats/laws/MonadWriterLaws.scala index 07c55eb656..8a3a386e99 100644 --- a/laws/src/main/scala/cats/laws/MonadWriterLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadWriterLaws.scala @@ -2,22 +2,23 @@ package cats package laws trait MonadWriterLaws[F[_], W] extends MonadLaws[F] { - implicit override def F: MonadWriter[F, W] + implicit def FW: MonadWriter[F, W] + implicit def F = FW.monad def monadWriterWriterPure[A](a: A)(implicit W: Monoid[W]): IsEq[F[A]] = - F.writer((W.empty, a)) <-> F.pure(a) + FW.writer((W.empty, a)) <-> F.pure(a) def monadWriterTellFusion(x: W, y: W)(implicit W: Monoid[W]): IsEq[F[Unit]] = - F.flatMap(F.tell(x))(_ => F.tell(y)) <-> F.tell(W.combine(x, y)) + F.flatMap(FW.tell(x))(_ => FW.tell(y)) <-> FW.tell(W.combine(x, y)) def monadWriterListenPure[A](a: A)(implicit W: Monoid[W]): IsEq[F[(W, A)]] = - F.listen(F.pure(a)) <-> F.pure((W.empty, a)) + FW.listen(F.pure(a)) <-> F.pure((W.empty, a)) def monadWriterListenWriter[A](aw: (W, A)): IsEq[F[(W, A)]] = - F.listen(F.writer(aw)) <-> F.map(F.tell(aw._1))(_ => aw) + FW.listen(FW.writer(aw)) <-> F.map(FW.tell(aw._1))(_ => aw) } object MonadWriterLaws { - def apply[F[_], W](implicit FW: MonadWriter[F, W]): MonadWriterLaws[F, W] = - new MonadWriterLaws[F, W] { def F: MonadWriter[F, W] = FW } + def apply[F[_], W](implicit FW0: MonadWriter[F, W]): MonadWriterLaws[F, W] = + new MonadWriterLaws[F, W] { def FW: MonadWriter[F, W] = FW0 } } From 22642ac1a35b53e37c455915288ff1502986ea3a Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 13:13:06 -0700 Subject: [PATCH 04/12] Ambiguous implicits fix for ApplicativeError and MonadError --- .../main/scala/cats/ApplicativeError.scala | 18 +++++++------ core/src/main/scala/cats/MonadError.scala | 6 +++-- core/src/main/scala/cats/data/EitherT.scala | 13 +++++++--- core/src/main/scala/cats/data/Kleisli.scala | 12 ++++----- core/src/main/scala/cats/data/OptionT.scala | 14 ++++++----- core/src/main/scala/cats/data/Validated.scala | 6 +++-- core/src/main/scala/cats/data/WriterT.scala | 19 +++++++++++--- .../main/scala/cats/instances/either.scala | 6 +++-- .../main/scala/cats/instances/future.scala | 3 ++- .../main/scala/cats/instances/option.scala | 1 + core/src/main/scala/cats/instances/try.scala | 2 ++ free/src/main/scala/cats/free/FreeT.scala | 22 ++++++++-------- .../cats/laws/ApplicativeErrorLaws.scala | 25 ++++++++++--------- .../main/scala/cats/laws/MonadErrorLaws.scala | 7 +++--- .../test/scala/cats/tests/OptionTTests.scala | 1 + .../test/scala/cats/tests/WriterTTests.scala | 1 + 16 files changed, 95 insertions(+), 61 deletions(-) diff --git a/core/src/main/scala/cats/ApplicativeError.scala b/core/src/main/scala/cats/ApplicativeError.scala index 4f36625205..f38c07a2d4 100644 --- a/core/src/main/scala/cats/ApplicativeError.scala +++ b/core/src/main/scala/cats/ApplicativeError.scala @@ -9,7 +9,9 @@ import scala.util.control.NonFatal * * This type class allows one to abstract over error-handling applicatives. */ -trait ApplicativeError[F[_], E] extends Applicative[F] { +trait ApplicativeError[F[_], E] { + def applicative: Applicative[F] + /** * Lift an error into the `F` context. */ @@ -34,7 +36,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] { * * @see [[recover]] to only recover from certain errors. */ - def handleError[A](fa: F[A])(f: E => A): F[A] = handleErrorWith(fa)(f andThen pure) + def handleError[A](fa: F[A])(f: E => A): F[A] = handleErrorWith(fa)(f andThen applicative.pure) /** * Handle errors by turning them into [[scala.util.Either]] values. @@ -44,8 +46,8 @@ trait ApplicativeError[F[_], E] extends Applicative[F] { * All non-fatal errors should be handled by this method. */ def attempt[A](fa: F[A]): F[Either[E, A]] = handleErrorWith( - map(fa)(Right(_): Either[E, A]) - )(e => pure(Left(e))) + applicative.map(fa)(Right(_): Either[E, A]) + )(e => applicative.pure(Left(e))) /** * Similar to [[attempt]], but wraps the result in a [[cats.data.EitherT]] for @@ -63,7 +65,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] { */ def recover[A](fa: F[A])(pf: PartialFunction[E, A]): F[A] = handleErrorWith(fa)(e => - (pf andThen pure) applyOrElse(e, raiseError)) + (pf andThen applicative.pure) applyOrElse(e, raiseError)) /** * Recover from certain errors by mapping them to an `F[A]` value. @@ -81,7 +83,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] { * and raise. */ def catchNonFatal[A](a: => A)(implicit ev: Throwable <:< E): F[A] = - try pure(a) + try applicative.pure(a) catch { case NonFatal(e) => raiseError(e) } @@ -91,7 +93,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] { * and raise */ def catchNonFatalEval[A](a: Eval[A])(implicit ev: Throwable <:< E): F[A] = - try pure(a.value) + try applicative.pure(a.value) catch { case NonFatal(e) => raiseError(e) } @@ -101,7 +103,7 @@ trait ApplicativeError[F[_], E] extends Applicative[F] { */ def fromTry[A](t: Try[A])(implicit ev: Throwable <:< E): F[A] = t match { - case Success(a) => pure(a) + case Success(a) => applicative.pure(a) case Failure(e) => raiseError(e) } } diff --git a/core/src/main/scala/cats/MonadError.scala b/core/src/main/scala/cats/MonadError.scala index 512a041123..0d7441ead7 100644 --- a/core/src/main/scala/cats/MonadError.scala +++ b/core/src/main/scala/cats/MonadError.scala @@ -5,13 +5,15 @@ package cats * * This type class allows one to abstract over error-handling monads. */ -trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] { +trait MonadError[F[_], E] extends ApplicativeError[F, E] { + def monad: Monad[F] + def applicative = monad /** * Turns a successful value into an error if it does not satisfy a given predicate. */ def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A] = - flatMap(fa)(a => if (predicate(a)) pure(a) else raiseError(error)) + monad.flatMap(fa)(a => if (predicate(a)) applicative.pure(a) else raiseError(error)) } diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index 38eab701fe..dc024419ac 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -282,6 +282,9 @@ private[data] abstract class EitherTInstances extends EitherTInstances1 { } */ + implicit def catsDataMonadErrorForEitherT[F[_], L](implicit F0: Monad[F]): MonadError[EitherT[F, L, ?], L] = + new EitherTMonadError[F, L] { implicit val F = F0 } + implicit def catsDataOrderForEitherT[F[_], L, R](implicit F: Order[F[Either[L, R]]]): Order[EitherT[F, L, R]] = new EitherTOrder[F, L, R] { val F0: Order[F[Either[L, R]]] = F @@ -342,8 +345,8 @@ private[data] abstract class EitherTInstances1 extends EitherTInstances2 { } private[data] abstract class EitherTInstances2 extends EitherTInstances3 { - implicit def catsDataMonadErrorForEitherT[F[_], L](implicit F0: Monad[F]): MonadError[EitherT[F, L, ?], L] = - new EitherTMonadError[F, L] { implicit val F = F0 } + implicit def catsDataMonadForEitherT[F[_], L](implicit F0: Monad[F]): Monad[EitherT[F, L, ?]] = + new EitherTMonad[F, L] { implicit val F = F0 } implicit def catsDataRecursiveTailRecMForEitherT[F[_]: RecursiveTailRecM, L]: RecursiveTailRecM[EitherT[F, L, ?]] = RecursiveTailRecM.create[EitherT[F, L, ?]] @@ -399,7 +402,9 @@ private[data] trait EitherTMonad[F[_], L] extends Monad[EitherT[F, L, ?]] with E })) } -private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, ?], L] with EitherTMonad[F, L] { +private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, ?], L] { outer => + implicit val F: Monad[F] + def monad = new EitherTMonad[F, L] { implicit val F = outer.F } def handleErrorWith[A](fea: EitherT[F, L, A])(f: L => EitherT[F, L, A]): EitherT[F, L, A] = EitherT(F.flatMap(fea.value) { case Left(e) => f(e).value @@ -418,7 +423,7 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, fla.recoverWith(pf) } -private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] with EitherTMonadError[F, L] { +private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] with EitherTMonad[F, L] { implicit val F: Monad[F] implicit val L: Monoid[L] def empty[A]: EitherT[F, L, A] = EitherT(F.pure(Either.left(L.empty))) diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 068d812eb8..72f08b3c87 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -130,7 +130,7 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 { } implicit def catsDataApplicativeErrorForKleisli[F[_], A, E](implicit AE: ApplicativeError[F, E]): ApplicativeError[Kleisli[F, A, ?], E] - = new KleisliApplicativeError[F, A, E] { implicit def AF: ApplicativeError[F, E] = AE } + = new KleisliApplicativeError[F, A, E] { implicit def F: ApplicativeError[F, E] = AE } } private[data] sealed abstract class KleisliInstances0 extends KleisliInstances1 { @@ -283,17 +283,17 @@ private trait KleisliMonoidK[F[_]] extends MonoidK[λ[α => Kleisli[F, α, α]]] } -private trait KleisliApplicativeError[F[_], A, E] extends KleisliApplicative[F, A] with ApplicativeError[Kleisli[F, A, ?], E] { +private trait KleisliApplicativeError[F[_], A, E] extends ApplicativeError[Kleisli[F, A, ?], E] { outer => type K[T] = Kleisli[F, A, T] - implicit def AF: ApplicativeError[F, E] + implicit def F: ApplicativeError[F, E] - implicit def F: Applicative[F] = AF + def applicative = new KleisliApplicative[F, A] { implicit def F = outer.F.applicative } - def raiseError[B](e: E): K[B] = Kleisli(_ => AF.raiseError(e)) + def raiseError[B](e: E): K[B] = Kleisli(_ => F.raiseError(e)) def handleErrorWith[B](kb: K[B])(f: E => K[B]): K[B] = Kleisli { a: A => - AF.handleErrorWith(kb.run(a))((e: E) => f(e).run(a)) + F.handleErrorWith(kb.run(a))((e: E) => f(e).run(a)) } } diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 364a8e4583..4ddb360ed8 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -179,6 +179,9 @@ private[data] sealed trait OptionTInstances extends OptionTInstances0 { implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = new OptionTMonad[F] { implicit val F = F0 } + implicit def catsDataMonadErrorForOptionT[F[_], E](implicit F0: MonadError[F, E]): MonadError[OptionT[F, ?], E] = + new OptionTMonadError[F, E] { implicit val F = F0 } + implicit def catsDataFoldableForOptionT[F[_]](implicit F0: Foldable[F]): Foldable[OptionT[F, ?]] = new OptionTFoldable[F] { implicit val F = F0 } @@ -193,9 +196,6 @@ private[data] sealed trait OptionTInstances extends OptionTInstances0 { } private[data] sealed trait OptionTInstances0 extends OptionTInstances1 { - implicit def catsDataMonadErrorForOptionT[F[_], E](implicit F0: MonadError[F, E]): MonadError[OptionT[F, ?], E] = - new OptionTMonadError[F, E] { implicit val F = F0 } - implicit def catsDataRecursiveTailRecMForOptionT[F[_]](implicit F: RecursiveTailRecM[F]): RecursiveTailRecM[OptionT[F, ?]] = RecursiveTailRecM.create[OptionT[F, ?]] @@ -259,11 +259,13 @@ private[data] trait OptionTMonad[F[_]] extends Monad[OptionT[F, ?]] { ))) } -private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] with OptionTMonad[F] { - override def F: MonadError[F, E] +private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] { outer => + def F: MonadError[F, E] + + def monad = new OptionTMonad[F] { implicit def F = outer.F.monad } override def raiseError[A](e: E): OptionT[F, A] = - OptionT(F.map(F.raiseError[A](e))(Some(_))) + OptionT(F.monad.map(F.raiseError[A](e))(Some(_))) override def handleErrorWith[A](fa: OptionT[F, A])(f: E => OptionT[F, A]): OptionT[F, A] = OptionT(F.handleErrorWith(fa.value)(f(_).value)) diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala index d55915dab5..88af686263 100644 --- a/core/src/main/scala/cats/data/Validated.scala +++ b/core/src/main/scala/cats/data/Validated.scala @@ -280,8 +280,10 @@ private[data] sealed abstract class ValidatedInstances extends ValidatedInstance fab.leftMap(f) } - 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] { + implicit def catsDataInstancesForValidated[E](implicit E: Semigroup[E]): Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] with Applicative[Validated[E, ?]]= + new Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] with Applicative[Validated[E, ?]] { + val applicative = this + def traverse[F[_]: Applicative, A, B](fa: Validated[E, A])(f: A => F[B]): F[Validated[E, B]] = fa.traverse(f) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 98d48011a7..fe7fc4960f 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -324,8 +324,14 @@ private[data] sealed trait WriterTMonad[F[_], L] extends WriterTApplicative[F, L } -private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends ApplicativeError[WriterT[F, L, ?], E] with WriterTApplicative[F, L] { - override implicit def F0: ApplicativeError[F, E] +private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends ApplicativeError[WriterT[F, L, ?], E] { outer => + implicit def F0: ApplicativeError[F, E] + implicit def L0: Monoid[L] + + def applicative = new WriterTApplicative[F, L] { + implicit def F0 = outer.F0.applicative + implicit def L0 = outer.L0 + } def raiseError[A](e: E): WriterT[F, L, A] = WriterT(F0.raiseError[(L, A)](e)) @@ -333,8 +339,15 @@ private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends Applicati WriterT(F0.handleErrorWith(fa.run)(e => f(e).run)) } -private[data] sealed trait WriterTMonadError[F[_], L, E] extends MonadError[WriterT[F, L, ?], E] with WriterTMonad[F, L] with WriterTApplicativeError[F, L, E]{ +private[data] sealed trait WriterTMonadError[F[_], L, E] extends MonadError[WriterT[F, L, ?], E] with WriterTApplicativeError[F, L, E] { outer => override implicit def F0: MonadError[F, E] + + def monad = new WriterTMonad[F, L] { + implicit def F0 = outer.F0.monad + implicit def L0 = outer.L0 + } + + override def applicative = monad } private[data] sealed trait WriterTMonadWriter[F[_], L] extends MonadWriter[WriterT[F, L, ?], L] { outer => diff --git a/core/src/main/scala/cats/instances/either.scala b/core/src/main/scala/cats/instances/either.scala index 64777fd181..18d67196aa 100644 --- a/core/src/main/scala/cats/instances/either.scala +++ b/core/src/main/scala/cats/instances/either.scala @@ -28,8 +28,10 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances { } // scalastyle:off method.length - implicit def catsStdInstancesForEither[A]: MonadError[Either[A, ?], A] with Traverse[Either[A, ?]] with RecursiveTailRecM[Either[A, ?]] = - new MonadError[Either[A, ?], A] with Traverse[Either[A, ?]] with RecursiveTailRecM[Either[A, ?]] { + implicit def catsStdInstancesForEither[A]: MonadError[Either[A, ?], A] with Monad[Either[A, ?]] with Traverse[Either[A, ?]] with RecursiveTailRecM[Either[A, ?]] = + new MonadError[Either[A, ?], A] with Monad[Either[A, ?]] with Traverse[Either[A, ?]] with RecursiveTailRecM[Either[A, ?]] { + val monad = this + def pure[B](b: B): Either[A, B] = Right(b) def flatMap[B, C](fa: Either[A, B])(f: B => Either[A, C]): Either[A, C] = diff --git a/core/src/main/scala/cats/instances/future.scala b/core/src/main/scala/cats/instances/future.scala index 216a56c426..a3bf72084e 100644 --- a/core/src/main/scala/cats/instances/future.scala +++ b/core/src/main/scala/cats/instances/future.scala @@ -5,9 +5,10 @@ import scala.util.control.NonFatal import scala.concurrent.{ExecutionContext, Future} trait FutureInstances extends FutureInstances1 { - implicit def catsStdInstancesForFuture(implicit ec: ExecutionContext): MonadError[Future, Throwable] with CoflatMap[Future] with Monad[Future] with RecursiveTailRecM[Future] = new FutureCoflatMap with MonadError[Future, Throwable] with Monad[Future] with RecursiveTailRecM[Future] { + val monad = this + def pure[A](x: A): Future[A] = Future.successful(x) def flatMap[A, B](fa: Future[A])(f: A => Future[B]): Future[B] = fa.flatMap(f) diff --git a/core/src/main/scala/cats/instances/option.scala b/core/src/main/scala/cats/instances/option.scala index b9ca152996..7dc679655b 100644 --- a/core/src/main/scala/cats/instances/option.scala +++ b/core/src/main/scala/cats/instances/option.scala @@ -7,6 +7,7 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances { implicit val catsStdInstancesForOption: TraverseFilter[Option] with MonadError[Option, Unit] with MonadCombine[Option] with Monad[Option] with CoflatMap[Option] with Alternative[Option] with RecursiveTailRecM[Option] = new TraverseFilter[Option] with MonadError[Option, Unit] with MonadCombine[Option] with Monad[Option] with CoflatMap[Option] with Alternative[Option] with RecursiveTailRecM[Option] { + val monad = this def empty[A]: Option[A] = None diff --git a/core/src/main/scala/cats/instances/try.scala b/core/src/main/scala/cats/instances/try.scala index e96d6bb511..7bac78dde3 100644 --- a/core/src/main/scala/cats/instances/try.scala +++ b/core/src/main/scala/cats/instances/try.scala @@ -12,6 +12,8 @@ trait TryInstances extends TryInstances1 { // scalastyle:off method.length implicit def catsStdInstancesForTry: MonadError[Try, Throwable] with CoflatMap[Try] with Traverse[Try] with Monad[Try] with RecursiveTailRecM[Try] = new TryCoflatMap with MonadError[Try, Throwable] with Traverse[Try] with Monad[Try] with RecursiveTailRecM[Try] { + val monad = this + def pure[A](x: A): Try[A] = Success(x) override def product[A, B](ta: Try[A], tb: Try[B]): Try[(A, B)] = (ta, tb) match { diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala index b7e0578389..b0336473bd 100644 --- a/free/src/main/scala/cats/free/FreeT.scala +++ b/free/src/main/scala/cats/free/FreeT.scala @@ -172,18 +172,7 @@ object FreeT extends FreeTInstances { } -private[free] sealed trait FreeTInstances2 { - implicit def catsFreeMonadErrorForFreeT[S[_], M[_]: RecursiveTailRecM, E](implicit E: MonadError[M, E]): MonadError[FreeT[S, M, ?], E] = - new MonadError[FreeT[S, M, ?], E] with FreeTMonad[S, M] { - override def M = implicitly - override def handleErrorWith[A](fa: FreeT[S, M, A])(f: E => FreeT[S, M, A]) = - FreeT.liftT[S, M, FreeT[S, M, A]](E.handleErrorWith(fa.toM)(f.andThen(_.toM)))(M).flatMap(identity) - override def raiseError[A](e: E) = - FreeT.liftT(E.raiseError[A](e))(M) - } -} - -private[free] sealed trait FreeTInstances1 extends FreeTInstances2 { +private[free] sealed trait FreeTInstances1 { implicit def catsFreeFlatMapForFreeT[S[_], M[_]](implicit M0: Applicative[M]): FlatMap[FreeT[S, M, ?]] = new FreeTFlatMap[S, M] { implicit def M: Applicative[M] = M0 @@ -213,6 +202,15 @@ private[free] sealed trait FreeTInstances0 extends FreeTInstances1 { } private[free] sealed trait FreeTInstances extends FreeTInstances0 { + implicit def catsFreeMonadErrorForFreeT[S[_], M[_]: RecursiveTailRecM, E](implicit E: MonadError[M, E]): MonadError[FreeT[S, M, ?], E] = + new MonadError[FreeT[S, M, ?], E] { + val monad = catsFreeMonadForFreeT[S, M](E.monad) + override def handleErrorWith[A](fa: FreeT[S, M, A])(f: E => FreeT[S, M, A]) = + FreeT.liftT[S, M, FreeT[S, M, A]](E.handleErrorWith(fa.toM(E.monad))(f.andThen(_.toM(E.monad))))(E.monad).flatMap(identity) + override def raiseError[A](e: E) = + FreeT.liftT(E.raiseError[A](e))(E.monad) + } + implicit def catsFreeMonadStateForFreeT[S[_], M[_], E](implicit M1: MonadState[M, E]): MonadState[FreeT[S, M, ?], E] = new MonadState[FreeT[S, M, ?], E] { val monad = catsFreeMonadForFreeT[S, M](M1.monad) diff --git a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala index 6dd12d4e21..cba908b171 100644 --- a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala +++ b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala @@ -5,40 +5,41 @@ import cats.data.EitherT // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Error/Class/index.html trait ApplicativeErrorLaws[F[_], E] extends ApplicativeLaws[F] { - implicit override def F: ApplicativeError[F, E] + implicit def FE: ApplicativeError[F, E] + implicit def F = FE.applicative def applicativeErrorHandleWith[A](e: E, f: E => F[A]): IsEq[F[A]] = - F.handleErrorWith(F.raiseError[A](e))(f) <-> f(e) + FE.handleErrorWith(FE.raiseError[A](e))(f) <-> f(e) def applicativeErrorHandle[A](e: E, f: E => A): IsEq[F[A]] = - F.handleError(F.raiseError[A](e))(f) <-> F.pure(f(e)) + FE.handleError(FE.raiseError[A](e))(f) <-> F.pure(f(e)) def handleErrorWithPure[A](a: A, f: E => F[A]): IsEq[F[A]] = - F.handleErrorWith(F.pure(a))(f) <-> F.pure(a) + FE.handleErrorWith(F.pure(a))(f) <-> F.pure(a) def handleErrorPure[A](a: A, f: E => A): IsEq[F[A]] = - F.handleError(F.pure(a))(f) <-> F.pure(a) + FE.handleError(F.pure(a))(f) <-> F.pure(a) def raiseErrorAttempt(e: E): IsEq[F[Either[E, Unit]]] = - F.attempt(F.raiseError[Unit](e)) <-> F.pure(Left(e)) + FE.attempt(FE.raiseError[Unit](e)) <-> F.pure(Left(e)) def pureAttempt[A](a: A): IsEq[F[Either[E, A]]] = - F.attempt(F.pure(a)) <-> F.pure(Right(a)) + FE.attempt(F.pure(a)) <-> F.pure(Right(a)) def handleErrorWithConsistentWithRecoverWith[A](fa: F[A], f: E => F[A]): IsEq[F[A]] = - F.handleErrorWith(fa)(f) <-> F.recoverWith(fa)(PartialFunction(f)) + FE.handleErrorWith(fa)(f) <-> FE.recoverWith(fa)(PartialFunction(f)) def handleErrorConsistentWithRecover[A](fa: F[A], f: E => A): IsEq[F[A]] = - F.handleError(fa)(f) <-> F.recover(fa)(PartialFunction(f)) + FE.handleError(fa)(f) <-> FE.recover(fa)(PartialFunction(f)) def recoverConsistentWithRecoverWith[A](fa: F[A], pf: PartialFunction[E, A]): IsEq[F[A]] = - F.recover(fa)(pf) <-> F.recoverWith(fa)(pf andThen F.pure) + FE.recover(fa)(pf) <-> FE.recoverWith(fa)(pf andThen F.pure) def attemptConsistentWithAttemptT[A](fa: F[A]): IsEq[EitherT[F, E, A]] = - EitherT(F.attempt(fa)) <-> F.attemptT(fa) + EitherT(FE.attempt(fa)) <-> FE.attemptT(fa) } object ApplicativeErrorLaws { def apply[F[_], E](implicit ev: ApplicativeError[F, E]): ApplicativeErrorLaws[F, E] = - new ApplicativeErrorLaws[F, E] { def F: ApplicativeError[F, E] = ev } + new ApplicativeErrorLaws[F, E] { def FE: ApplicativeError[F, E] = ev } } diff --git a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala index d1b129e3a0..c33e0e5a8d 100644 --- a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala @@ -3,13 +3,14 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Error/Class/index.html trait MonadErrorLaws[F[_], E] extends ApplicativeErrorLaws[F, E] with MonadLaws[F] { - implicit override def F: MonadError[F, E] + implicit override def FE: MonadError[F, E] + implicit override def F = FE.monad def monadErrorLeftZero[A, B](e: E, f: A => F[B]): IsEq[F[B]] = - F.flatMap(F.raiseError[A](e))(f) <-> F.raiseError[B](e) + F.flatMap(FE.raiseError[A](e))(f) <-> FE.raiseError[B](e) } object MonadErrorLaws { def apply[F[_], E](implicit ev: MonadError[F, E]): MonadErrorLaws[F, E] = - new MonadErrorLaws[F, E] { def F: MonadError[F, E] = ev } + new MonadErrorLaws[F, E] { def FE: MonadError[F, E] = ev } } diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index 041d72d0e0..9d13152a1d 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -71,6 +71,7 @@ class OptionTTests extends CatsSuite { type SEither[A] = Either[String, A] implicit val monadError = OptionT.catsDataMonadErrorForOptionT[SEither, String] + implicit val monad = OptionT.catsDataMonadForOptionT[SEither] import org.scalacheck.Arbitrary implicit val arb1 = implicitly[Arbitrary[OptionT[SEither, Int]]] diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index b41c680b23..fdd9a2e80f 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -353,6 +353,7 @@ class WriterTTests extends CatsSuite { // F has an ApplicativeError and L has a Monoid implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] implicit val appErr = WriterT.catsDataApplicativeErrorForWriterT[Validated[String, ?], ListWrapper[Int], String] + implicit val app = WriterT.catsDataApplicativeForWriterT[Validated[String, ?], ListWrapper[Int]] implicit val iso = CartesianTests.Isomorphisms.invariant[WriterT[Validated[String, ?], ListWrapper[Int], ?]] implicit def eq1[A:Eq]: Eq[WriterT[Validated[String, ?], ListWrapper[Int], A]] = WriterT.catsDataEqForWriterT[Validated[String, ?], ListWrapper[Int], A] From c87f3e08578f626777d53fa08bea3a272b3b249c Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 13:14:40 -0700 Subject: [PATCH 05/12] Annotate types for MTL laws --- laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala | 2 +- laws/src/main/scala/cats/laws/MonadErrorLaws.scala | 2 +- laws/src/main/scala/cats/laws/MonadReaderLaws.scala | 2 +- laws/src/main/scala/cats/laws/MonadStateLaws.scala | 2 +- laws/src/main/scala/cats/laws/MonadWriterLaws.scala | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala index cba908b171..53ac9bd818 100644 --- a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala +++ b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala @@ -6,7 +6,7 @@ import cats.data.EitherT // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Error/Class/index.html trait ApplicativeErrorLaws[F[_], E] extends ApplicativeLaws[F] { implicit def FE: ApplicativeError[F, E] - implicit def F = FE.applicative + implicit def F: Applicative[F] = FE.applicative def applicativeErrorHandleWith[A](e: E, f: E => F[A]): IsEq[F[A]] = FE.handleErrorWith(FE.raiseError[A](e))(f) <-> f(e) diff --git a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala index c33e0e5a8d..0ea97f4b65 100644 --- a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala @@ -4,7 +4,7 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Error/Class/index.html trait MonadErrorLaws[F[_], E] extends ApplicativeErrorLaws[F, E] with MonadLaws[F] { implicit override def FE: MonadError[F, E] - implicit override def F = FE.monad + implicit override def F: Monad[F] = FE.monad def monadErrorLeftZero[A, B](e: E, f: A => F[B]): IsEq[F[B]] = F.flatMap(FE.raiseError[A](e))(f) <-> FE.raiseError[B](e) diff --git a/laws/src/main/scala/cats/laws/MonadReaderLaws.scala b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala index 2e96be2569..3600433217 100644 --- a/laws/src/main/scala/cats/laws/MonadReaderLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala @@ -4,7 +4,7 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Reader/Class/index.html trait MonadReaderLaws[F[_], R] extends MonadLaws[F] { implicit def FR: MonadReader[F, R] - implicit def F = FR.monad + implicit def F: Monad[F] = FR.monad val monadReaderAskIdempotent: IsEq[F[R]] = F.flatMap(FR.ask)(_ => FR.ask) <-> FR.ask diff --git a/laws/src/main/scala/cats/laws/MonadStateLaws.scala b/laws/src/main/scala/cats/laws/MonadStateLaws.scala index 4eb7ebe5b4..0f942190b4 100644 --- a/laws/src/main/scala/cats/laws/MonadStateLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadStateLaws.scala @@ -4,7 +4,7 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/State/Class/index.html trait MonadStateLaws[F[_], S] extends MonadLaws[F] { implicit def FS: MonadState[F, S] - implicit def F = FS.monad + implicit def F: Monad[F] = FS.monad val monadStateGetIdempotent: IsEq[F[S]] = F.flatMap(FS.get)(_ => FS.get) <-> FS.get diff --git a/laws/src/main/scala/cats/laws/MonadWriterLaws.scala b/laws/src/main/scala/cats/laws/MonadWriterLaws.scala index 8a3a386e99..abdb44c807 100644 --- a/laws/src/main/scala/cats/laws/MonadWriterLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadWriterLaws.scala @@ -3,7 +3,7 @@ package laws trait MonadWriterLaws[F[_], W] extends MonadLaws[F] { implicit def FW: MonadWriter[F, W] - implicit def F = FW.monad + implicit def F: Monad[F] = FW.monad def monadWriterWriterPure[A](a: A)(implicit W: Monoid[W]): IsEq[F[A]] = FW.writer((W.empty, a)) <-> F.pure(a) From 1b14a7767636fc3466573229a024e00bf2ba4a0b Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 17:27:25 -0700 Subject: [PATCH 06/12] Ambiguous implicits fix for {Functor, Traverse, Monad}Filter, Alternative, and MonadCombine --- core/src/main/scala/cats/Alternative.scala | 6 ++- core/src/main/scala/cats/Composed.scala | 22 ++++++++-- core/src/main/scala/cats/FunctorFilter.scala | 3 +- core/src/main/scala/cats/MonadCombine.scala | 10 +++-- core/src/main/scala/cats/MonadError.scala | 2 +- core/src/main/scala/cats/MonadFilter.scala | 6 ++- core/src/main/scala/cats/TraverseFilter.scala | 7 ++-- core/src/main/scala/cats/data/Const.scala | 19 +++++---- core/src/main/scala/cats/data/EitherT.scala | 10 ++++- core/src/main/scala/cats/data/Ior.scala | 2 +- core/src/main/scala/cats/data/Nested.scala | 18 +++++++-- core/src/main/scala/cats/data/OneAnd.scala | 24 ++++++----- core/src/main/scala/cats/data/OptionT.scala | 34 ++++++++++++---- core/src/main/scala/cats/data/Prod.scala | 8 +++- core/src/main/scala/cats/data/StateT.scala | 12 +++--- core/src/main/scala/cats/data/WriterT.scala | 27 +++++++++++-- core/src/main/scala/cats/instances/list.scala | 28 ++++++++----- core/src/main/scala/cats/instances/map.scala | 5 ++- .../main/scala/cats/instances/option.scala | 34 +++++++++------- .../main/scala/cats/instances/stream.scala | 27 ++++++++----- .../main/scala/cats/instances/vector.scala | 29 +++++++++----- core/src/main/scala/cats/syntax/either.scala | 2 +- free/src/main/scala/cats/free/FreeT.scala | 6 ++- .../scala/cats/laws/AlternativeLaws.scala | 9 +++-- .../scala/cats/laws/FunctorFilterLaws.scala | 5 ++- .../scala/cats/laws/MonadCombineLaws.scala | 7 ++-- .../scala/cats/laws/MonadFilterLaws.scala | 11 ++--- .../main/scala/cats/laws/MonoidKLaws.scala | 8 ++-- .../main/scala/cats/laws/SemigroupKLaws.scala | 6 +-- .../scala/cats/laws/TraverseFilterLaws.scala | 5 ++- .../test/scala/cats/tests/ListWrapper.scala | 40 ++++++++++++------- .../test/scala/cats/tests/NestedTests.scala | 2 +- .../test/scala/cats/tests/OptionTTests.scala | 2 +- .../test/scala/cats/tests/StateTTests.scala | 3 +- .../test/scala/cats/tests/WriterTTests.scala | 19 +++++---- 35 files changed, 296 insertions(+), 162 deletions(-) diff --git a/core/src/main/scala/cats/Alternative.scala b/core/src/main/scala/cats/Alternative.scala index 343de9ced4..de402811a3 100644 --- a/core/src/main/scala/cats/Alternative.scala +++ b/core/src/main/scala/cats/Alternative.scala @@ -2,8 +2,10 @@ package cats import simulacrum.typeclass -@typeclass trait Alternative[F[_]] extends Applicative[F] with MonoidK[F] { self => - override def compose[G[_]: Applicative]: Alternative[λ[α => F[G[α]]]] = +@typeclass trait Alternative[F[_]] extends MonoidK[F] { self => + def applicativeInstance: Applicative[F] + + def compose[G[_]: Applicative]: Alternative[λ[α => F[G[α]]]] = new ComposedAlternative[F, G] { val F = self val G = Applicative[G] diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala index e8f5552f1b..7e9de095ec 100644 --- a/core/src/main/scala/cats/Composed.scala +++ b/core/src/main/scala/cats/Composed.scala @@ -48,8 +48,14 @@ private[cats] trait ComposedMonoidK[F[_], G[_]] extends MonoidK[λ[α => F[G[α] override def empty[A]: F[G[A]] = F.empty } -private[cats] trait ComposedAlternative[F[_], G[_]] extends Alternative[λ[α => F[G[α]]]] with ComposedApplicative[F, G] with ComposedMonoidK[F, G] { outer => +private[cats] trait ComposedAlternative[F[_], G[_]] extends Alternative[λ[α => F[G[α]]]] with ComposedMonoidK[F, G] { outer => def F: Alternative[F] + def G: Applicative[G] + + def applicativeInstance = new ComposedApplicative[F, G] { + def F = outer.F.applicativeInstance + def G = outer.G + } } private[cats] trait ComposedFoldable[F[_], G[_]] extends Foldable[λ[α => F[G[α]]]] { outer => @@ -71,18 +77,28 @@ private[cats] trait ComposedTraverse[F[_], G[_]] extends Traverse[λ[α => F[G[ F.traverse(fga)(ga => G.traverse(ga)(f)) } -private[cats] trait ComposedTraverseFilter[F[_], G[_]] extends TraverseFilter[λ[α => F[G[α]]]] with ComposedTraverse[F, G] { +private[cats] trait ComposedTraverseFilter[F[_], G[_]] extends TraverseFilter[λ[α => F[G[α]]]] { outer => def F: Traverse[F] def G: TraverseFilter[G] + def traverseInstance = new ComposedTraverse[F, G] { + def F = outer.F + def G = outer.G.traverseInstance + } + override def traverseFilter[H[_]: Applicative, A, B](fga: F[G[A]])(f: A => H[Option[B]]): H[F[G[B]]] = F.traverse[H, G[A], G[B]](fga)(ga => G.traverseFilter(ga)(f)) } -private[cats] trait ComposedFunctorFilter[F[_], G[_]] extends FunctorFilter[λ[α => F[G[α]]]] with ComposedFunctor[F, G] { +private[cats] trait ComposedFunctorFilter[F[_], G[_]] extends FunctorFilter[λ[α => F[G[α]]]] { outer => def F: Functor[F] def G: FunctorFilter[G] + def functorInstance = new ComposedFunctor[F, G] { + def F = outer.F + def G = outer.G.functorInstance + } + override def mapFilter[A, B](fga: F[G[A]])(f: A => Option[B]): F[G[B]] = F.map(fga)(G.mapFilter(_)(f)) } diff --git a/core/src/main/scala/cats/FunctorFilter.scala b/core/src/main/scala/cats/FunctorFilter.scala index cbbb5755de..19b6cd2133 100644 --- a/core/src/main/scala/cats/FunctorFilter.scala +++ b/core/src/main/scala/cats/FunctorFilter.scala @@ -2,7 +2,8 @@ package cats import simulacrum.typeclass -@typeclass trait FunctorFilter[F[_]] extends Functor[F] { +@typeclass trait FunctorFilter[F[_]] { + def functorInstance: Functor[F] /** * A combined [[map]] and [[filter]]. Filtering is handled via `Option` diff --git a/core/src/main/scala/cats/MonadCombine.scala b/core/src/main/scala/cats/MonadCombine.scala index a418cba774..f191f50915 100644 --- a/core/src/main/scala/cats/MonadCombine.scala +++ b/core/src/main/scala/cats/MonadCombine.scala @@ -6,6 +6,8 @@ import simulacrum.typeclass * The combination of a Monad with a MonoidK */ @typeclass trait MonadCombine[F[_]] extends MonadFilter[F] with Alternative[F] { + def monadInstance: Monad[F] + def applicativeInstance: Applicative[F] = monadInstance /** * Fold over the inner structure to combine all of the values with @@ -15,14 +17,14 @@ import simulacrum.typeclass * we collect all the Right values, etc. */ def unite[G[_], A](fga: F[G[A]])(implicit G: Foldable[G]): F[A] = - flatMap(fga) { ga => - G.foldLeft(ga, empty[A])((acc, a) => combineK(acc, pure(a))) + monadInstance.flatMap(fga) { ga => + G.foldLeft(ga, empty[A])((acc, a) => combineK(acc, applicativeInstance.pure(a))) } /** Separate the inner foldable values into the "lefts" and "rights" */ def separate[G[_, _], A, B](fgab: F[G[A, B]])(implicit G: Bifoldable[G]): (F[A], F[B]) = { - val as = flatMap(fgab)(gab => G.bifoldMap(gab)(pure, _ => empty[A])(algebra[A])) - val bs = flatMap(fgab)(gab => G.bifoldMap(gab)(_ => empty[B], pure)(algebra[B])) + val as = monadInstance.flatMap(fgab)(gab => G.bifoldMap(gab)(applicativeInstance.pure, _ => empty[A])(algebra[A])) + val bs = monadInstance.flatMap(fgab)(gab => G.bifoldMap(gab)(_ => empty[B], applicativeInstance.pure)(algebra[B])) (as, bs) } } diff --git a/core/src/main/scala/cats/MonadError.scala b/core/src/main/scala/cats/MonadError.scala index 0d7441ead7..d5bc571b81 100644 --- a/core/src/main/scala/cats/MonadError.scala +++ b/core/src/main/scala/cats/MonadError.scala @@ -7,7 +7,7 @@ package cats */ trait MonadError[F[_], E] extends ApplicativeError[F, E] { def monad: Monad[F] - def applicative = monad + def applicative: Applicative[F] = monad /** * Turns a successful value into an error if it does not satisfy a given predicate. diff --git a/core/src/main/scala/cats/MonadFilter.scala b/core/src/main/scala/cats/MonadFilter.scala index e2099a49e2..1a0337f9de 100644 --- a/core/src/main/scala/cats/MonadFilter.scala +++ b/core/src/main/scala/cats/MonadFilter.scala @@ -9,10 +9,12 @@ import simulacrum.typeclass * us since it allows us to add a `filter` method to a Monad, which is * used when pattern matching or using guards in for comprehensions. */ -@typeclass trait MonadFilter[F[_]] extends Monad[F] with FunctorFilter[F] { +@typeclass trait MonadFilter[F[_]] extends FunctorFilter[F] { + def monadInstance: Monad[F] + def functorInstance: Functor[F] = monadInstance def empty[A]: F[A] override def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B] = - flatMap(fa)(a => f(a).fold(empty[B])(pure)) + monadInstance.flatMap(fa)(a => f(a).fold(empty[B])(monadInstance.pure)) } diff --git a/core/src/main/scala/cats/TraverseFilter.scala b/core/src/main/scala/cats/TraverseFilter.scala index 9e6c1ebac6..52efa2a05e 100644 --- a/core/src/main/scala/cats/TraverseFilter.scala +++ b/core/src/main/scala/cats/TraverseFilter.scala @@ -11,7 +11,9 @@ import simulacrum.typeclass * * Based on Haskell's [[https://hackage.haskell.org/package/witherable-0.1.3.3/docs/Data-Witherable.html Data.Witherable]] */ -@typeclass trait TraverseFilter[F[_]] extends Traverse[F] with FunctorFilter[F] { self => +@typeclass trait TraverseFilter[F[_]] extends FunctorFilter[F] { self => + def traverseInstance : Traverse[F] + def functorInstance: Functor[F] = traverseInstance /** * A combined [[traverse]] and [[filter]]. Filtering is handled via `Option` @@ -59,7 +61,4 @@ import simulacrum.typeclass override def filter[A](fa: F[A])(f: A => Boolean): F[A] = filterA[Id, A](fa)(f) - - override def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = - traverseFilter(fa)(a => G.map(f(a))(Some(_))) } diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index 65b0132ce0..fe438a789e 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -56,17 +56,20 @@ private[data] sealed abstract class ConstInstances extends ConstInstances0 { fa.retag[B] } - implicit def catsDataTraverseFilterForConst[C]: TraverseFilter[Const[C, ?]] = new TraverseFilter[Const[C, ?]] { - def traverseFilter[G[_]: Applicative, A, B](fa: Const[C, A])(f: A => G[Option[B]]): G[Const[C, B]] = - fa.traverseFilter(f) + implicit def catsDataTraverseFilterForConst[C]: TraverseFilter[Const[C, ?]] with Traverse[Const[C, ?]] = + new TraverseFilter[Const[C, ?]] with Traverse[Const[C, ?]] { + val traverseInstance = this - def foldLeft[A, B](fa: Const[C, A], b: B)(f: (B, A) => B): B = b + def traverseFilter[G[_]: Applicative, A, B](fa: Const[C, A])(f: A => G[Option[B]]): G[Const[C, B]] = + fa.traverseFilter(f) - def foldRight[A, B](fa: Const[C, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = lb + def foldLeft[A, B](fa: Const[C, A], b: B)(f: (B, A) => B): B = b - override def traverse[G[_]: Applicative, A, B](fa: Const[C, A])(f: A => G[B]): G[Const[C, B]] = - fa.traverse(f) - } + def foldRight[A, B](fa: Const[C, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = lb + + override def traverse[G[_]: Applicative, A, B](fa: Const[C, A])(f: A => G[B]): G[Const[C, B]] = + fa.traverse(f) + } implicit def catsDataMonoidForConst[A: Monoid, B]: Monoid[Const[A, B]] = new Monoid[Const[A, B]]{ def empty: Const[A, B] = diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index dc024419ac..904e12b72b 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -60,7 +60,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) { F.map(value)(_.to[G]) def collectRight(implicit F: MonadCombine[F]): F[B] = - F.flatMap(value)(_.to[F]) + F.monadInstance.flatMap(value)(_.to[F]) def bimap[C, D](fa: A => C, fb: B => D)(implicit F: Functor[F]): EitherT[F, C, D] = EitherT(F.map(value)(_.bimap(fa, fb))) @@ -423,9 +423,15 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, fla.recoverWith(pf) } -private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] with EitherTMonad[F, L] { +private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] { outer => implicit val F: Monad[F] implicit val L: Monoid[L] + + implicit def monad = new EitherTMonad[F, L] { + implicit val F = outer.F + implicit val L = outer.L + } + def empty[A]: EitherT[F, L, A] = EitherT(F.pure(Either.left(L.empty))) } diff --git a/core/src/main/scala/cats/data/Ior.scala b/core/src/main/scala/cats/data/Ior.scala index 4adf44d61d..833662fd2c 100644 --- a/core/src/main/scala/cats/data/Ior.scala +++ b/core/src/main/scala/cats/data/Ior.scala @@ -46,7 +46,7 @@ sealed abstract class Ior[+A, +B] extends Product with Serializable { final def toList: List[B] = right.toList final def to[F[_], BB >: B](implicit F: Alternative[F]): F[BB] = - fold(_ => F.empty, F.pure, (_, b) => F.pure(b)) + fold(_ => F.empty, F.applicativeInstance.pure, (_, b) => F.applicativeInstance.pure(b)) final def swap: B Ior A = fold(Ior.right, Ior.left, (a, b) => Ior.both(b, a)) diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index fc5fb50873..b2d425ca75 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -154,8 +154,10 @@ private[data] trait NestedFunctor[F[_], G[_]] extends Functor[Nested[F, G, ?]] w Nested(FG.map(fga.value)(f)) } -private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested[F, G, ?]] with NestedFunctor[F, G] { - override def FG: FunctorFilter[λ[α => F[G[α]]]] +private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested[F, G, ?]] { outer => + def FG: FunctorFilter[λ[α => F[G[α]]]] + + def functorInstance = new NestedFunctor[F, G] { def FG = outer.FG.functorInstance } override def mapFilter[A, B](fga: Nested[F, G, A])(f: A => Option[B]): Nested[F, G, B] = Nested(FG.mapFilter(fga.value)(f)) @@ -167,9 +169,15 @@ private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested Nested(FG.filter(fga.value)(f)) } -private[data] trait NestedTraverseFilter[F[_], G[_]] extends TraverseFilter[Nested[F, G, ?]] with NestedFunctorFilter[F, G] with NestedTraverse[F, G] { +private[data] trait NestedTraverseFilter[F[_], G[_]] extends TraverseFilter[Nested[F, G, ?]] with NestedFunctorFilter[F, G] { outer => override def FG: TraverseFilter[λ[α => F[G[α]]]] + def traverseInstance = new NestedTraverse[F, G] { + def FG = outer.FG.traverseInstance + } + + override def functorInstance = traverseInstance + override def traverseFilter[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[Option[B]]): H[Nested[F, G, B]] = Applicative[H].map(FG.traverseFilter(fga.value)(f))(Nested(_)) } @@ -202,8 +210,10 @@ private[data] trait NestedMonoidK[F[_], G[_]] extends MonoidK[Nested[F, G, ?]] w 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] { +private[data] trait NestedAlternative[F[_], G[_]] extends Alternative[Nested[F, G, ?]] with NestedMonoidK[F, G] { outer => def FG: Alternative[λ[α => F[G[α]]]] + + def applicativeInstance = new NestedApplicative[F, G] { def FG = outer.FG.applicativeInstance } } private[data] trait NestedFoldable[F[_], G[_]] extends Foldable[Nested[F, G, ?]] { diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index ee50730ebb..c29e6dd11f 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -20,21 +20,21 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) { * Combine the head and tail into a single `F[A]` value. */ def unwrap(implicit F: MonadCombine[F]): F[A] = - F.combineK(F.pure(head), tail) + F.combineK(F.monadInstance.pure(head), tail) /** * remove elements not matching the predicate */ def filter(f: A => Boolean)(implicit F: MonadCombine[F]): F[A] = { val rest = F.filter(tail)(f) - if (f(head)) F.combineK(F.pure(head), rest) else rest + if (f(head)) F.combineK(F.monadInstance.pure(head), rest) else rest } /** * Append another OneAnd to this */ def combine(other: OneAnd[F, A])(implicit F: MonadCombine[F]): OneAnd[F, A] = - OneAnd(head, F.combineK(tail, F.combineK(F.pure(other.head), other.tail))) + OneAnd(head, F.combineK(tail, F.combineK(F.monadInstance.pure(other.head), other.tail))) /** * find the first element matching the predicate, if one exists @@ -120,7 +120,8 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { override def size[A](fa: OneAnd[F, A]): Long = 1 + F.size(fa.tail) } - implicit def catsDataMonadForOneAnd[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[F, ?]] = + implicit def catsDataMonadForOneAnd[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[F, ?]] = { + implicit val monadInstance = monad.monadInstance new Monad[OneAnd[F, ?]] { override def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] = fa map f @@ -129,9 +130,9 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { OneAnd(x, monad.empty) def flatMap[A, B](fa: OneAnd[F, A])(f: A => OneAnd[F, B]): OneAnd[F, B] = { - val end = monad.flatMap(fa.tail) { a => + val end = monadInstance.flatMap(fa.tail) { a => val fa = f(a) - monad.combineK(monad.pure(fa.head), fa.tail) + monad.combineK(monadInstance.pure(fa.head), fa.tail) } val fst = f(fa.head) OneAnd(fst.head, monad.combineK(fst.tail, end)) @@ -140,11 +141,11 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { def tailRecM[A, B](a: A)(fn: A => OneAnd[F, Either[A, B]]): OneAnd[F, B] = { def stepF(a: A): F[Either[A, B]] = { val oneAnd = fn(a) - monad.combineK(monad.pure(oneAnd.head), oneAnd.tail) + monad.combineK(monadInstance.pure(oneAnd.head), oneAnd.tail) } def toFB(in: Either[A, B]): F[B] = in match { - case Right(b) => monad.pure(b) - case Left(a) => monad.tailRecM(a)(stepF) + case Right(b) => monadInstance.pure(b) + case Left(a) => monadInstance.tailRecM(a)(stepF) } // This could probably be in SemigroupK to perform well @@ -159,16 +160,17 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { def go(in: A, rest: List[F[B]]): OneAnd[F, B] = fn(in) match { case OneAnd(Right(b), tail) => - val fbs = monad.flatMap(tail)(toFB) + val fbs = monadInstance.flatMap(tail)(toFB) OneAnd(b, combineAll(fbs :: rest)) case OneAnd(Left(a), tail) => - val fbs = monad.flatMap(tail)(toFB) + val fbs = monadInstance.flatMap(tail)(toFB) go(a, fbs :: rest) } go(a, Nil) } } + } implicit def catsDataOneAnd[F[_]: RecursiveTailRecM]: RecursiveTailRecM[OneAnd[F, ?]] = RecursiveTailRecM.create[OneAnd[F, ?]] diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 4ddb360ed8..2da5bc0f00 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -176,6 +176,12 @@ object OptionT extends OptionTInstances { } private[data] sealed trait OptionTInstances extends OptionTInstances0 { + implicit def catsDataTraverseFilterForOptionT[F[_]](implicit F0: Traverse[F]): TraverseFilter[OptionT[F, ?]] = + new OptionTTraverseFilter[F] { implicit val F = F0 } + + implicit def catsDataFunctorFilterForOptionT[F[_]](implicit F0: Functor[F]): FunctorFilter[OptionT[F, ?]] = + new OptionTFunctorFilter[F] { implicit val F = F0 } + implicit def catsDataMonadForOptionT[F[_]](implicit F0: Monad[F]): Monad[OptionT[F, ?]] = new OptionTMonad[F] { implicit val F = F0 } @@ -226,19 +232,25 @@ private[data] sealed trait OptionTInstances1 extends OptionTInstances2 { } private[data] sealed trait OptionTInstances2 extends OptionTInstances3 { - implicit def catsDataTraverseForOptionT[F[_]](implicit F0: Traverse[F]): TraverseFilter[OptionT[F, ?]] = - new OptionTTraverseFilter[F] { implicit val F = F0 } + implicit def catsDataTraverseForOptionT[F[_]](implicit F0: Traverse[F]): Traverse[OptionT[F, ?]] = + new OptionTTraverse[F] { implicit val F = F0 } } private[data] sealed trait OptionTInstances3 { - implicit def catsDataFunctorFilterForOptionT[F[_]](implicit F0: Functor[F]): FunctorFilter[OptionT[F, ?]] = + implicit def catsDataFunctorForOptionT[F[_]](implicit F0: Functor[F]): Functor[OptionT[F, ?]] = new OptionTFunctor[F] { implicit val F = F0 } } -private[data] trait OptionTFunctor[F[_]] extends FunctorFilter[OptionT[F, ?]] { +private[data] trait OptionTFunctor[F[_]] extends Functor[OptionT[F, ?]] { implicit def F: Functor[F] override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = fa.map(f) +} + +private[data] trait OptionTFunctorFilter[F[_]] extends FunctorFilter[OptionT[F, ?]] { outer => + implicit def F: Functor[F] + + def functorInstance = new OptionTFunctor[F] { implicit def F = outer.F } override def mapFilter[A, B](fa: OptionT[F, A])(f: A => Option[B]): OptionT[F, B] = fa.mapFilter(f) @@ -281,16 +293,22 @@ private[data] trait OptionTFoldable[F[_]] extends Foldable[OptionT[F, ?]] { fa.foldRight(lb)(f) } -private[data] sealed trait OptionTTraverseFilter[F[_]] extends TraverseFilter[OptionT[F, ?]] with OptionTFoldable[F] { +private[data] sealed trait OptionTTraverse[F[_]] extends Traverse[OptionT[F, ?]] with OptionTFoldable[F] { implicit def F: Traverse[F] - def traverseFilter[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[Option[B]]): G[OptionT[F, B]] = - fa traverseFilter f - override def traverse[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[B]): G[OptionT[F, B]] = fa traverse f } +private[data] sealed trait OptionTTraverseFilter[F[_]] extends TraverseFilter[OptionT[F, ?]] { outer => + implicit def F: Traverse[F] + + def traverseInstance = new OptionTTraverse[F] { implicit def F = outer.F } + + def traverseFilter[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[Option[B]]): G[OptionT[F, B]] = + fa traverseFilter f +} + private[data] trait OptionTSemigroup[F[_], A] extends Semigroup[OptionT[F, A]] { implicit val F: Semigroup[F[Option[A]]] diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index 493ff8073b..ff2af123f6 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -104,8 +104,12 @@ sealed trait ProdMonoidK[F[_], G[_]] extends MonoidK[λ[α => Prod[F, G, α]]] w Prod(F.empty[A], G.empty[A]) } -sealed trait ProdAlternative[F[_], G[_]] extends Alternative[λ[α => Prod[F, G, α]]] - with ProdApplicative[F, G] with ProdMonoidK[F, G] { +sealed trait ProdAlternative[F[_], G[_]] extends Alternative[λ[α => Prod[F, G, α]]] with ProdMonoidK[F, G] { outer => def F: Alternative[F] def G: Alternative[G] + + def applicativeInstance = new ProdApplicative[F, G] { + def F = outer.F.applicativeInstance + def G = outer.G.applicativeInstance + } } diff --git a/core/src/main/scala/cats/data/StateT.scala b/core/src/main/scala/cats/data/StateT.scala index db0ae87cc5..a47583a90e 100644 --- a/core/src/main/scala/cats/data/StateT.scala +++ b/core/src/main/scala/cats/data/StateT.scala @@ -162,7 +162,7 @@ private[data] sealed trait StateTInstances extends StateTInstances1 { private[data] sealed trait StateTInstances1 extends StateTInstances2 { implicit def catsDataMonadCombineForStateT[F[_], S](implicit F0: MonadCombine[F]): MonadCombine[StateT[F, S, ?]] = - new StateTMonadCombine[F, S] { implicit def F = F0 } + new StateTMonadCombine[F, S] { implicit def G = F0 } } private[data] sealed trait StateTInstances2 { @@ -249,9 +249,11 @@ private[data] sealed trait StateTSemigroupK[F[_], S] extends SemigroupK[StateT[F StateT(s => G.combineK(x.run(s), y.run(s))) } -private[data] sealed trait StateTMonadCombine[F[_], S] extends MonadCombine[StateT[F, S, ?]] with StateTMonad[F, S] with StateTSemigroupK[F, S] with StateTTransLift[S] { - implicit def F: MonadCombine[F] - override def G: MonadCombine[F] = F +private[data] sealed trait StateTMonadCombine[F[_], S] extends MonadCombine[StateT[F, S, ?]] with StateTSemigroupK[F, S] with StateTTransLift[S] { outer => + implicit def F = G.monadInstance + override def G: MonadCombine[F] - def empty[A]: StateT[F, S, A] = liftT[F, A](F.empty[A]) + def monadInstance = new StateTMonad[F, S] { implicit def F = outer.G.monadInstance } + + def empty[A]: StateT[F, S, A] = liftT[F, A](G.empty[A])(F) } diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index fe7fc4960f..b36b9eafc9 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -384,18 +384,37 @@ private[data] sealed trait WriterTMonoidK[F[_], L] extends MonoidK[WriterT[F, L, def empty[A]: WriterT[F, L, A] = WriterT(F0.empty) } -private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[WriterT[F, L, ?]] with WriterTMonoidK[F, L] with WriterTApplicative[F, L] { +private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[WriterT[F, L, ?]] with WriterTMonoidK[F, L] { outer => override implicit def F0: Alternative[F] + implicit def L0: Monoid[L] + + def applicativeInstance = new WriterTApplicative[F, L] { + def F0 = outer.F0.applicativeInstance + def L0 = outer.L0 + } } -private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[WriterT[F, L, ?]] with WriterTMonad[F, L] { - override implicit def F0: MonadFilter[F] +private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[WriterT[F, L, ?]] { outer => + implicit def F0: MonadFilter[F] + implicit def L0: Monoid[L] + + def monadInstance = new WriterTMonad[F, L] { + def F0 = outer.F0.monadInstance + def L0 = outer.L0 + } def empty[A]: WriterT[F, L, A] = WriterT(F0.empty) } -private[data] sealed trait WriterTMonadCombine[F[_], L] extends MonadCombine[WriterT[F, L, ?]] with WriterTMonad[F, L] with WriterTAlternative[F, L] { +private[data] sealed trait WriterTMonadCombine[F[_], L] extends MonadCombine[WriterT[F, L, ?]] with WriterTAlternative[F, L] { outer => override implicit def F0: MonadCombine[F] + + def monadInstance = new WriterTMonad[F, L] { + def F0 = outer.F0.monadInstance + def L0 = outer.L0 + } + + override def applicativeInstance = monadInstance } private[data] sealed trait WriterTSemigroup[F[_], L, A] extends Semigroup[WriterT[F, L, A]] { diff --git a/core/src/main/scala/cats/instances/list.scala b/core/src/main/scala/cats/instances/list.scala index bf982d8eed..0e7630cf2b 100644 --- a/core/src/main/scala/cats/instances/list.scala +++ b/core/src/main/scala/cats/instances/list.scala @@ -6,14 +6,26 @@ import cats.syntax.show._ import scala.annotation.tailrec import scala.collection.mutable.ListBuffer -trait ListInstances extends cats.kernel.instances.ListInstances { +trait ListInstances extends cats.kernel.instances.ListInstances with ListInstances0 { + implicit val catsStdMonadCombineForList: MonadCombine[List] = new MonadCombine[List] { + val monadInstance = catsStdInstancesForList - implicit val catsStdInstancesForList: TraverseFilter[List] with MonadCombine[List] with Monad[List] with CoflatMap[List] with RecursiveTailRecM[List] = - new TraverseFilter[List] with MonadCombine[List] with Monad[List] with CoflatMap[List] with RecursiveTailRecM[List] { + def empty[A]: List[A] = Nil - def empty[A]: List[A] = Nil + def combineK[A](x: List[A], y: List[A]): List[A] = x ++ y + } - def combineK[A](x: List[A], y: List[A]): List[A] = x ++ y + implicit def catsStdShowForList[A:Show]: Show[List[A]] = + new Show[List[A]] { + def show(fa: List[A]): String = + fa.iterator.map(_.show).mkString("List(", ", ", ")") + } +} + +private[instances] trait ListInstances0 { + implicit val catsStdInstancesForList: TraverseFilter[List] with Traverse[List] with Monad[List] with CoflatMap[List] with RecursiveTailRecM[List] = + new TraverseFilter[List] with Traverse[List] with Monad[List] with CoflatMap[List] with RecursiveTailRecM[List] { + val traverseInstance = this def pure[A](x: A): List[A] = x :: Nil @@ -81,10 +93,4 @@ trait ListInstances extends cats.kernel.instances.ListInstances { override def filter[A](fa: List[A])(f: A => Boolean): List[A] = fa.filter(f) } - - implicit def catsStdShowForList[A:Show]: Show[List[A]] = - new Show[List[A]] { - def show(fa: List[A]): String = - fa.iterator.map(_.show).mkString("List(", ", ", ")") - } } diff --git a/core/src/main/scala/cats/instances/map.scala b/core/src/main/scala/cats/instances/map.scala index 682a627b36..d6dae3653b 100644 --- a/core/src/main/scala/cats/instances/map.scala +++ b/core/src/main/scala/cats/instances/map.scala @@ -14,8 +14,9 @@ trait MapInstances extends cats.kernel.instances.MapInstances { } // scalastyle:off method.length - implicit def catsStdInstancesForMap[K]: TraverseFilter[Map[K, ?]] with FlatMap[Map[K, ?]] with RecursiveTailRecM[Map[K, ?]] = - new TraverseFilter[Map[K, ?]] with FlatMap[Map[K, ?]] with RecursiveTailRecM[Map[K, ?]] { + implicit def catsStdInstancesForMap[K]: TraverseFilter[Map[K, ?]] with Traverse[Map[K, ?]] with FlatMap[Map[K, ?]] with RecursiveTailRecM[Map[K, ?]] = + new TraverseFilter[Map[K, ?]] with Traverse[Map[K, ?]] with FlatMap[Map[K, ?]] with RecursiveTailRecM[Map[K, ?]] { + val traverseInstance = this override def traverse[G[_], A, B](fa: Map[K, A])(f: A => G[B])(implicit G: Applicative[G]): G[Map[K, B]] = { val gba: Eval[G[Map[K, B]]] = Always(G.pure(Map.empty)) diff --git a/core/src/main/scala/cats/instances/option.scala b/core/src/main/scala/cats/instances/option.scala index 7dc679655b..93e6400fc0 100644 --- a/core/src/main/scala/cats/instances/option.scala +++ b/core/src/main/scala/cats/instances/option.scala @@ -3,15 +3,29 @@ package instances import scala.annotation.tailrec -trait OptionInstances extends cats.kernel.instances.OptionInstances { +trait OptionInstances extends cats.kernel.instances.OptionInstances with OptionInstances0 { + implicit val catsStdMonadCombineForOption: MonadCombine[Option] = new MonadCombine[Option] { + val monadInstance = catsStdInstancesForOption - implicit val catsStdInstancesForOption: TraverseFilter[Option] with MonadError[Option, Unit] with MonadCombine[Option] with Monad[Option] with CoflatMap[Option] with Alternative[Option] with RecursiveTailRecM[Option] = - new TraverseFilter[Option] with MonadError[Option, Unit] with MonadCombine[Option] with Monad[Option] with CoflatMap[Option] with Alternative[Option] with RecursiveTailRecM[Option] { - val monad = this + def empty[A]: Option[A] = None - def empty[A]: Option[A] = None + def combineK[A](x: Option[A], y: Option[A]): Option[A] = x orElse y + } - def combineK[A](x: Option[A], y: Option[A]): Option[A] = x orElse y + implicit def catsStdShowForOption[A](implicit A: Show[A]): Show[Option[A]] = + new Show[Option[A]] { + def show(fa: Option[A]): String = fa match { + case Some(a) => s"Some(${A.show(a)})" + case None => "None" + } + } +} + +private[instances] trait OptionInstances0 { + implicit val catsStdInstancesForOption: TraverseFilter[Option] with Traverse[Option] with MonadError[Option, Unit] with Monad[Option] with CoflatMap[Option] with RecursiveTailRecM[Option] = + new TraverseFilter[Option] with Traverse[Option] with MonadError[Option, Unit] with Monad[Option] with CoflatMap[Option] with RecursiveTailRecM[Option] { + val monad = this + val traverseInstance = this def pure[A](x: A): Option[A] = Some(x) @@ -81,12 +95,4 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances { override def isEmpty[A](fa: Option[A]): Boolean = fa.isEmpty } - - implicit def catsStdShowForOption[A](implicit A: Show[A]): Show[Option[A]] = - new Show[Option[A]] { - def show(fa: Option[A]): String = fa match { - case Some(a) => s"Some(${A.show(a)})" - case None => "None" - } - } } diff --git a/core/src/main/scala/cats/instances/stream.scala b/core/src/main/scala/cats/instances/stream.scala index 904358fb63..89c6d3aca4 100644 --- a/core/src/main/scala/cats/instances/stream.scala +++ b/core/src/main/scala/cats/instances/stream.scala @@ -4,13 +4,25 @@ package instances import cats.syntax.show._ import scala.annotation.tailrec -trait StreamInstances extends cats.kernel.instances.StreamInstances { - implicit val catsStdInstancesForStream: TraverseFilter[Stream] with MonadCombine[Stream] with CoflatMap[Stream] with RecursiveTailRecM[Stream] = - new TraverseFilter[Stream] with MonadCombine[Stream] with CoflatMap[Stream] with RecursiveTailRecM[Stream] { +trait StreamInstances extends cats.kernel.instances.StreamInstances with StreamInstances0 { + implicit val catsStdMonadCombineForStream: MonadCombine[Stream] = new MonadCombine[Stream] { + val monadInstance = catsStdInstancesForStream - def empty[A]: Stream[A] = Stream.Empty + def empty[A]: Stream[A] = Stream.Empty - def combineK[A](x: Stream[A], y: Stream[A]): Stream[A] = x #::: y + def combineK[A](x: Stream[A], y: Stream[A]): Stream[A] = x #::: y + } + + implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] = + new Show[Stream[A]] { + def show(fa: Stream[A]): String = if (fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)" + } +} + +private[instances] trait StreamInstances0 { + implicit val catsStdInstancesForStream: TraverseFilter[Stream] with Traverse[Stream] with Monad[Stream] with CoflatMap[Stream] with RecursiveTailRecM[Stream] = + new TraverseFilter[Stream] with Traverse[Stream] with Monad[Stream] with CoflatMap[Stream] with RecursiveTailRecM[Stream] { + val traverseInstance = this def pure[A](x: A): Stream[A] = Stream(x) @@ -107,9 +119,4 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances { override def collect[A, B](fa: Stream[A])(f: PartialFunction[A, B]): Stream[B] = fa.collect(f) } - - implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] = - new Show[Stream[A]] { - def show(fa: Stream[A]): String = if (fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)" - } } diff --git a/core/src/main/scala/cats/instances/vector.scala b/core/src/main/scala/cats/instances/vector.scala index cdbf80f94d..21c5c1d1b3 100644 --- a/core/src/main/scala/cats/instances/vector.scala +++ b/core/src/main/scala/cats/instances/vector.scala @@ -6,13 +6,26 @@ import scala.annotation.tailrec import scala.collection.+: import scala.collection.immutable.VectorBuilder -trait VectorInstances extends cats.kernel.instances.VectorInstances { - implicit val catsStdInstancesForVector: TraverseFilter[Vector] with MonadCombine[Vector] with CoflatMap[Vector] with RecursiveTailRecM[Vector] = - new TraverseFilter[Vector] with MonadCombine[Vector] with CoflatMap[Vector] with RecursiveTailRecM[Vector] { +trait VectorInstances extends cats.kernel.instances.VectorInstances with VectorInstances0 { + implicit val catsStdMonadCombineForVector: MonadCombine[Vector] = new MonadCombine[Vector] { + val monadInstance = catsStdInstancesForVector - def empty[A]: Vector[A] = Vector.empty[A] + def empty[A]: Vector[A] = Vector.empty[A] - def combineK[A](x: Vector[A], y: Vector[A]): Vector[A] = x ++ y + def combineK[A](x: Vector[A], y: Vector[A]): Vector[A] = x ++ y + } + + implicit def catsStdShowForVector[A:Show]: Show[Vector[A]] = + new Show[Vector[A]] { + def show(fa: Vector[A]): String = + fa.iterator.map(_.show).mkString("Vector(", ", ", ")") + } +} + +private[instances] trait VectorInstances0 { + implicit val catsStdInstancesForVector: TraverseFilter[Vector] with Traverse[Vector] with Monad[Vector] with CoflatMap[Vector] with RecursiveTailRecM[Vector] = + new TraverseFilter[Vector] with Traverse[Vector] with Monad[Vector] with CoflatMap[Vector] with RecursiveTailRecM[Vector] { + val traverseInstance = this def pure[A](x: A): Vector[A] = Vector(x) @@ -87,10 +100,4 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances { override def collect[A, B](fa: Vector[A])(f: PartialFunction[A, B]): Vector[B] = fa.collect(f) } - - implicit def catsStdShowForVector[A:Show]: Show[Vector[A]] = - new Show[Vector[A]] { - def show(fa: Vector[A]): String = - fa.iterator.map(_.show).mkString("Vector(", ", ", ")") - } } diff --git a/core/src/main/scala/cats/syntax/either.scala b/core/src/main/scala/cats/syntax/either.scala index c333a00e4a..f9fc621aec 100644 --- a/core/src/main/scala/cats/syntax/either.scala +++ b/core/src/main/scala/cats/syntax/either.scala @@ -98,7 +98,7 @@ final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal { def to[F[_]](implicit F: Alternative[F]): F[B] = eab match { case Left(_) => F.empty - case Right(b) => F.pure(b) + case Right(b) => F.applicativeInstance.pure(b) } def bimap[C, D](fa: A => C, fb: B => D): Either[C, D] = eab match { diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala index b0336473bd..55884deed4 100644 --- a/free/src/main/scala/cats/free/FreeT.scala +++ b/free/src/main/scala/cats/free/FreeT.scala @@ -221,10 +221,12 @@ private[free] sealed trait FreeTInstances extends FreeTInstances0 { } implicit def catsFreeMonadCombineForFreeT[S[_], M[_]: Alternative]: MonadCombine[FreeT[S, M, ?]] = - new MonadCombine[FreeT[S, M, ?]] with FreeTCombine[S, M] with FreeTMonad[S, M] { - override def M = implicitly + new MonadCombine[FreeT[S, M, ?]] with FreeTCombine[S, M] { + override def M = Alternative[M].applicativeInstance override def M1 = implicitly + def monadInstance = catsFreeMonadForFreeT[S, M](Alternative[M].applicativeInstance) + override def empty[A] = FreeT.liftT[S, M, A](MonoidK[M].empty[A])(M) } } diff --git a/laws/src/main/scala/cats/laws/AlternativeLaws.scala b/laws/src/main/scala/cats/laws/AlternativeLaws.scala index e8bb2f83b3..8465f96be0 100644 --- a/laws/src/main/scala/cats/laws/AlternativeLaws.scala +++ b/laws/src/main/scala/cats/laws/AlternativeLaws.scala @@ -4,11 +4,12 @@ package laws import cats.syntax.all._ trait AlternativeLaws[F[_]] extends ApplicativeLaws[F] with MonoidKLaws[F] { - implicit override def F: Alternative[F] - implicit def algebra[A]: Monoid[F[A]] = F.algebra[A] + implicit def F0: Alternative[F] + implicit def F: Applicative[F] = F0.applicativeInstance + implicit def algebra[A]: Monoid[F[A]] = F0.algebra[A] def alternativeRightAbsorption[A, B](ff: F[A => B]): IsEq[F[B]] = - (ff ap F.empty[A]) <-> F.empty[B] + (ff ap F0.empty[A]) <-> F0.empty[B] def alternativeLeftDistributivity[A, B](fa: F[A], fa2: F[A], f: A => B): IsEq[F[B]] = ((fa |+| fa2) map f) <-> ((fa map f) |+| (fa2 map f)) @@ -20,5 +21,5 @@ trait AlternativeLaws[F[_]] extends ApplicativeLaws[F] with MonoidKLaws[F] { object AlternativeLaws { def apply[F[_]](implicit ev: Alternative[F]): AlternativeLaws[F] = - new AlternativeLaws[F] { def F: Alternative[F] = ev } + new AlternativeLaws[F] { def F0: Alternative[F] = ev } } diff --git a/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala b/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala index d79de5dadc..d567f23f5c 100644 --- a/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala +++ b/laws/src/main/scala/cats/laws/FunctorFilterLaws.scala @@ -4,7 +4,8 @@ package laws import cats.implicits._ trait FunctorFilterLaws[F[_]] extends FunctorLaws[F] { - implicit override def F: FunctorFilter[F] + implicit def F0: FunctorFilter[F] + implicit def F: Functor[F] = F0.functorInstance def mapFilterComposition[A, B, C]( fa: F[A], @@ -31,5 +32,5 @@ trait FunctorFilterLaws[F[_]] extends FunctorLaws[F] { object FunctorFilterLaws { def apply[F[_]](implicit ev: FunctorFilter[F]): FunctorFilterLaws[F] = - new FunctorFilterLaws[F] { def F: FunctorFilter[F] = ev } + new FunctorFilterLaws[F] { def F0: FunctorFilter[F] = ev } } diff --git a/laws/src/main/scala/cats/laws/MonadCombineLaws.scala b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala index a8100e381d..fc20e21b60 100644 --- a/laws/src/main/scala/cats/laws/MonadCombineLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala @@ -7,13 +7,14 @@ import cats.syntax.all._ * Laws that must be obeyed by any `MonadCombine`. */ trait MonadCombineLaws[F[_]] extends MonadFilterLaws[F] with AlternativeLaws[F] { - implicit override def F: MonadCombine[F] + implicit override def F0: MonadCombine[F] + implicit override def F: Monad[F] = F0.monadInstance def monadCombineLeftDistributivity[A, B](fa: F[A], fa2: F[A], f: A => F[B]): IsEq[F[B]] = - F.combineK(fa, fa2).flatMap(f) <-> F.combineK(fa flatMap f, fa2 flatMap f) + F0.combineK(fa, fa2).flatMap(f) <-> F0.combineK(fa flatMap f, fa2 flatMap f) } object MonadCombineLaws { def apply[F[_]](implicit ev: MonadCombine[F]): MonadCombineLaws[F] = - new MonadCombineLaws[F] { def F: MonadCombine[F] = ev } + new MonadCombineLaws[F] { def F0: MonadCombine[F] = ev } } diff --git a/laws/src/main/scala/cats/laws/MonadFilterLaws.scala b/laws/src/main/scala/cats/laws/MonadFilterLaws.scala index 9116df2bba..a40951a974 100644 --- a/laws/src/main/scala/cats/laws/MonadFilterLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadFilterLaws.scala @@ -7,19 +7,20 @@ import cats.syntax.all._ * Laws that must be obeyed by any `MonadFilter`. */ trait MonadFilterLaws[F[_]] extends MonadLaws[F] with FunctorFilterLaws[F] { - implicit override def F: MonadFilter[F] + implicit override def F0: MonadFilter[F] + implicit override def F: Monad[F] = F0.monadInstance def monadFilterLeftEmpty[A, B](f: A => F[B]): IsEq[F[B]] = - F.empty[A].flatMap(f) <-> F.empty[B] + F0.empty[A].flatMap(f) <-> F0.empty[B] def monadFilterRightEmpty[A, B](fa: F[A]): IsEq[F[B]] = - fa.flatMap(_ => F.empty[B]) <-> F.empty[B] + fa.flatMap(_ => F0.empty[B]) <-> F0.empty[B] def monadFilterConsistency[A, B](fa: F[A], f: A => Boolean): IsEq[F[A]] = - fa.filter(f) <-> fa.flatMap(a => if (f(a)) F.pure(a) else F.empty) + fa.filter(f) <-> fa.flatMap(a => if (f(a)) F.pure(a) else F0.empty) } object MonadFilterLaws { def apply[F[_]](implicit ev: MonadFilter[F]): MonadFilterLaws[F] = - new MonadFilterLaws[F] { def F: MonadFilter[F] = ev } + new MonadFilterLaws[F] { def F0: MonadFilter[F] = ev } } diff --git a/laws/src/main/scala/cats/laws/MonoidKLaws.scala b/laws/src/main/scala/cats/laws/MonoidKLaws.scala index 8f2f3b600c..69308a2a90 100644 --- a/laws/src/main/scala/cats/laws/MonoidKLaws.scala +++ b/laws/src/main/scala/cats/laws/MonoidKLaws.scala @@ -5,16 +5,16 @@ package laws * Laws that must be obeyed by any `cats.MonoidK`. */ trait MonoidKLaws[F[_]] extends SemigroupKLaws[F] { - override implicit def F: MonoidK[F] + override implicit def F0: MonoidK[F] def monoidKLeftIdentity[A](a: F[A]): IsEq[F[A]] = - F.combineK(F.empty, a) <-> a + F0.combineK(F0.empty, a) <-> a def monoidKRightIdentity[A](a: F[A]): IsEq[F[A]] = - F.combineK(a, F.empty) <-> a + F0.combineK(a, F0.empty) <-> a } object MonoidKLaws { def apply[F[_]](implicit ev: MonoidK[F]): MonoidKLaws[F] = - new MonoidKLaws[F] { def F: MonoidK[F] = ev } + new MonoidKLaws[F] { def F0: MonoidK[F] = ev } } diff --git a/laws/src/main/scala/cats/laws/SemigroupKLaws.scala b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala index 34cd1792ce..0f11ae7e85 100644 --- a/laws/src/main/scala/cats/laws/SemigroupKLaws.scala +++ b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala @@ -5,13 +5,13 @@ package laws * Laws that must be obeyed by any `cats.SemigroupK`. */ trait SemigroupKLaws[F[_]] { - implicit def F: SemigroupK[F] + implicit def F0: SemigroupK[F] def semigroupKAssociative[A](a: F[A], b: F[A], c: F[A]): IsEq[F[A]] = - F.combineK(F.combineK(a, b), c) <-> F.combineK(a, F.combineK(b, c)) + F0.combineK(F0.combineK(a, b), c) <-> F0.combineK(a, F0.combineK(b, c)) } object SemigroupKLaws { def apply[F[_]](implicit ev: SemigroupK[F]): SemigroupKLaws[F] = - new SemigroupKLaws[F] { def F: SemigroupK[F] = ev } + new SemigroupKLaws[F] { def F0: SemigroupK[F] = ev } } diff --git a/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala b/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala index 8620d9b926..fb8a323280 100644 --- a/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala +++ b/laws/src/main/scala/cats/laws/TraverseFilterLaws.scala @@ -5,7 +5,8 @@ import cats.data.Nested import cats.implicits._ trait TraverseFilterLaws[F[_]] extends TraverseLaws[F] with FunctorFilterLaws[F] { - implicit override def F: TraverseFilter[F] + implicit override def F0: TraverseFilter[F] + implicit override def F: Traverse[F] = F0.traverseInstance def traverseFilterIdentity[G[_]:Applicative, A](fa: F[A]): IsEq[G[F[A]]] = { fa.traverseFilter(_.some.pure[G]) <-> fa.pure[G] @@ -29,5 +30,5 @@ trait TraverseFilterLaws[F[_]] extends TraverseLaws[F] with FunctorFilterLaws[F] object TraverseFilterLaws { def apply[F[_]](implicit ev: TraverseFilter[F]): TraverseFilterLaws[F] = - new TraverseFilterLaws[F] { def F: TraverseFilter[F] = ev } + new TraverseFilterLaws[F] { def F0: TraverseFilter[F] = ev } } diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 4c2dad7efa..b68cb788c1 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -48,17 +48,23 @@ object ListWrapper { val F = TraverseFilter[List] new TraverseFilter[ListWrapper] { - def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = - F.foldLeft(fa.list, b)(f) - def foldRight[A, B](fa: ListWrapper[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = - F.foldRight(fa.list, lb)(f) + val traverseInstance = traverse def traverseFilter[G[_], A, B](fa: ListWrapper[A])(f: A => G[Option[B]])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { G0.map(F.traverseFilter(fa.list)(f))(ListWrapper.apply) } } } - val traverse: Traverse[ListWrapper] = traverseFilter + val traverse: Traverse[ListWrapper] = new Traverse[ListWrapper] { + val F = Traverse[List] + + def traverse[G[_], A, B](fa: ListWrapper[A])(f: A => G[B])(implicit G: Applicative[G]): G[ListWrapper[B]] = + G.map(F.traverse(fa.list)(f))(ListWrapper(_)) + def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = + F.foldLeft(fa.list, b)(f) + def foldRight[A, B](fa: ListWrapper[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = + F.foldRight(fa.list, lb)(f) + } val foldable: Foldable[ListWrapper] = traverse @@ -80,27 +86,31 @@ object ListWrapper { val M = MonadCombine[List] new MonadCombine[ListWrapper] { - def pure[A](x: A): ListWrapper[A] = ListWrapper(M.pure(x)) - - def flatMap[A, B](fa: ListWrapper[A])(f: A => ListWrapper[B]): ListWrapper[B] = - ListWrapper(M.flatMap(fa.list)(a => f(a).list)) + val monadInstance = monad def empty[A]: ListWrapper[A] = ListWrapper(M.empty[A]) def combineK[A](x: ListWrapper[A], y: ListWrapper[A]): ListWrapper[A] = ListWrapper(M.combineK(x.list, y.list)) - - def tailRecM[A, B](a: A)(f: A => ListWrapper[Either[A,B]]): ListWrapper[B] = - ListWrapper(M.tailRecM(a)(a => f(a).list)) } } - val monad: Monad[ListWrapper] = monadCombine + val monad: Monad[ListWrapper] = new Monad[ListWrapper] { + val M = Monad[List] + + def pure[A](x: A): ListWrapper[A] = ListWrapper(M.pure(x)) + + def flatMap[A, B](fa: ListWrapper[A])(f: A => ListWrapper[B]): ListWrapper[B] = + ListWrapper(M.flatMap(fa.list)(a => f(a).list)) + + def tailRecM[A, B](a: A)(f: A => ListWrapper[Either[A,B]]): ListWrapper[B] = + ListWrapper(M.tailRecM(a)(a => f(a).list)) + } - val applicative: Applicative[ListWrapper] = monadCombine + val applicative: Applicative[ListWrapper] = monad /** apply is taken due to ListWrapper being a case class */ - val applyInstance: Apply[ListWrapper] = monadCombine + val applyInstance: Apply[ListWrapper] = monad def monoidK: MonoidK[ListWrapper] = monadCombine diff --git a/tests/src/test/scala/cats/tests/NestedTests.scala b/tests/src/test/scala/cats/tests/NestedTests.scala index 9063647450..8f612e4c6a 100644 --- a/tests/src/test/scala/cats/tests/NestedTests.scala +++ b/tests/src/test/scala/cats/tests/NestedTests.scala @@ -99,7 +99,7 @@ class NestedTests extends CatsSuite { { // Alternative composition - implicit val instance = ListWrapper.alternative + implicit val instance = ListWrapper.applicative checkAll("Nested[List, ListWrapper, ?]", AlternativeTests[Nested[List, ListWrapper, ?]].alternative[Int, Int, Int]) checkAll("Alternative[Nested[List, ListWrapper, ?]]", SerializableTests.serializable(Alternative[Nested[List, ListWrapper, ?]])) } diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index 9d13152a1d..d90cbfb078 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -7,7 +7,7 @@ import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ class OptionTTests extends CatsSuite { - implicit val iso = CartesianTests.Isomorphisms.invariant[OptionT[ListWrapper, ?]](OptionT.catsDataFunctorFilterForOptionT(ListWrapper.functor)) + implicit val iso = CartesianTests.Isomorphisms.invariant[OptionT[ListWrapper, ?]](OptionT.catsDataFunctorForOptionT(ListWrapper.functor)) { implicit val F = ListWrapper.eqv[Option[Int]] diff --git a/tests/src/test/scala/cats/tests/StateTTests.scala b/tests/src/test/scala/cats/tests/StateTTests.scala index 18fb0bb410..8a343884fa 100644 --- a/tests/src/test/scala/cats/tests/StateTTests.scala +++ b/tests/src/test/scala/cats/tests/StateTTests.scala @@ -196,7 +196,8 @@ class StateTTests extends CatsSuite { { // F has a MonadCombine - implicit def F = ListWrapper.monadCombine + implicit def F0 = ListWrapper.monadCombine + implicit def F1 = F0.monadInstance checkAll("StateT[ListWrapper, Int, Int]", MonadCombineTests[StateT[ListWrapper, Int, ?]].monadCombine[Int, Int, Int]) checkAll("MonadCombine[StateT[ListWrapper, Int, ?]]", SerializableTests.serializable(MonadCombine[StateT[ListWrapper, Int, ?]])) diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index fdd9a2e80f..c784a59cd6 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -145,7 +145,7 @@ class WriterTTests extends CatsSuite { // resolution and the laws of these various instances. { // F has an Apply and L has a Semigroup - implicit val F: Apply[ListWrapper] = ListWrapper.monadCombine + implicit val F: Apply[ListWrapper] = ListWrapper.applyInstance implicit val L: Semigroup[ListWrapper[Int]] = ListWrapper.semigroup[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -167,7 +167,7 @@ class WriterTTests extends CatsSuite { { // F has a Monad and L has a Semigroup - implicit val F: Monad[ListWrapper] = ListWrapper.monadCombine + implicit val F: Monad[ListWrapper] = ListWrapper.monad implicit val L: Semigroup[ListWrapper[Int]] = ListWrapper.semigroup[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -193,7 +193,7 @@ class WriterTTests extends CatsSuite { } { // F has a FlatMap and L has a Monoid - implicit val F: FlatMap[ListWrapper] = ListWrapper.monadCombine + implicit val F: FlatMap[ListWrapper] = ListWrapper.monad implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -220,7 +220,7 @@ class WriterTTests extends CatsSuite { { // F has an Applicative and L has a Monoid - implicit val F: Applicative[ListWrapper] = ListWrapper.monadCombine + implicit val F: Applicative[ListWrapper] = ListWrapper.monad implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -247,7 +247,7 @@ class WriterTTests extends CatsSuite { { // F has a Monad and L has a Monoid - implicit val F: Monad[ListWrapper] = ListWrapper.monadCombine + implicit val F: Monad[ListWrapper] = ListWrapper.monad implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -282,7 +282,8 @@ class WriterTTests extends CatsSuite { { // F has an Alternative and L has a Monoid - implicit val F: Alternative[ListWrapper] = ListWrapper.alternative + implicit val F0: Alternative[ListWrapper] = ListWrapper.alternative + implicit val F1 = F0.applicativeInstance implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -295,7 +296,8 @@ class WriterTTests extends CatsSuite { { // F has a MonadFilter and L has a Monoid - implicit val F: MonadFilter[ListWrapper] = ListWrapper.monadFilter + implicit val F0: MonadFilter[ListWrapper] = ListWrapper.monadFilter + implicit val F1 = F0.monadInstance implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -310,7 +312,8 @@ class WriterTTests extends CatsSuite { { // F has a MonadCombine and L has a Monoid - implicit val F: MonadCombine[ListWrapper] = ListWrapper.monadCombine + implicit val F0: MonadCombine[ListWrapper] = ListWrapper.monadCombine + implicit val F1 = F0.monadInstance implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] From b31c4b07efdad8c8a66702d2a12b72894fb376ed Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 19:50:57 -0700 Subject: [PATCH 07/12] Fix style-related stuff --- .../main/scala/cats/ApplicativeError.scala | 18 ++++++++--------- core/src/main/scala/cats/Composed.scala | 6 +++--- core/src/main/scala/cats/FunctorFilter.scala | 2 +- core/src/main/scala/cats/MonadError.scala | 6 +++--- core/src/main/scala/cats/MonadReader.scala | 4 ++-- core/src/main/scala/cats/MonadState.scala | 8 ++++---- core/src/main/scala/cats/MonadWriter.scala | 8 ++++---- core/src/main/scala/cats/SemigroupK.scala | 2 +- core/src/main/scala/cats/data/EitherT.scala | 4 ++-- core/src/main/scala/cats/data/Kleisli.scala | 5 +++-- core/src/main/scala/cats/data/Nested.scala | 9 +++++---- core/src/main/scala/cats/data/OneAnd.scala | 2 +- core/src/main/scala/cats/data/OptionT.scala | 8 ++++---- core/src/main/scala/cats/data/Prod.scala | 2 +- core/src/main/scala/cats/data/StateT.scala | 6 +++--- core/src/main/scala/cats/data/Validated.scala | 2 +- core/src/main/scala/cats/data/WriterT.scala | 20 +++++++++---------- .../main/scala/cats/instances/either.scala | 2 +- .../main/scala/cats/instances/function.scala | 2 +- .../main/scala/cats/instances/future.scala | 2 +- .../main/scala/cats/instances/option.scala | 2 +- core/src/main/scala/cats/instances/try.scala | 2 +- free/src/main/scala/cats/free/FreeT.scala | 12 +++++------ .../cats/laws/ApplicativeErrorLaws.scala | 2 +- .../main/scala/cats/laws/MonadErrorLaws.scala | 2 +- .../scala/cats/laws/MonadReaderLaws.scala | 2 +- .../main/scala/cats/laws/MonadStateLaws.scala | 2 +- .../scala/cats/laws/MonadWriterLaws.scala | 2 +- 28 files changed, 73 insertions(+), 71 deletions(-) diff --git a/core/src/main/scala/cats/ApplicativeError.scala b/core/src/main/scala/cats/ApplicativeError.scala index f38c07a2d4..5930cabfd8 100644 --- a/core/src/main/scala/cats/ApplicativeError.scala +++ b/core/src/main/scala/cats/ApplicativeError.scala @@ -9,8 +9,8 @@ import scala.util.control.NonFatal * * This type class allows one to abstract over error-handling applicatives. */ -trait ApplicativeError[F[_], E] { - def applicative: Applicative[F] +trait ApplicativeError[F[_], E] extends Serializable { + def applicativeInstance: Applicative[F] /** * Lift an error into the `F` context. @@ -36,7 +36,7 @@ trait ApplicativeError[F[_], E] { * * @see [[recover]] to only recover from certain errors. */ - def handleError[A](fa: F[A])(f: E => A): F[A] = handleErrorWith(fa)(f andThen applicative.pure) + def handleError[A](fa: F[A])(f: E => A): F[A] = handleErrorWith(fa)(f andThen applicativeInstance.pure) /** * Handle errors by turning them into [[scala.util.Either]] values. @@ -46,8 +46,8 @@ trait ApplicativeError[F[_], E] { * All non-fatal errors should be handled by this method. */ def attempt[A](fa: F[A]): F[Either[E, A]] = handleErrorWith( - applicative.map(fa)(Right(_): Either[E, A]) - )(e => applicative.pure(Left(e))) + applicativeInstance.map(fa)(Right(_): Either[E, A]) + )(e => applicativeInstance.pure(Left(e))) /** * Similar to [[attempt]], but wraps the result in a [[cats.data.EitherT]] for @@ -65,7 +65,7 @@ trait ApplicativeError[F[_], E] { */ def recover[A](fa: F[A])(pf: PartialFunction[E, A]): F[A] = handleErrorWith(fa)(e => - (pf andThen applicative.pure) applyOrElse(e, raiseError)) + (pf andThen applicativeInstance.pure) applyOrElse(e, raiseError)) /** * Recover from certain errors by mapping them to an `F[A]` value. @@ -83,7 +83,7 @@ trait ApplicativeError[F[_], E] { * and raise. */ def catchNonFatal[A](a: => A)(implicit ev: Throwable <:< E): F[A] = - try applicative.pure(a) + try applicativeInstance.pure(a) catch { case NonFatal(e) => raiseError(e) } @@ -93,7 +93,7 @@ trait ApplicativeError[F[_], E] { * and raise */ def catchNonFatalEval[A](a: Eval[A])(implicit ev: Throwable <:< E): F[A] = - try applicative.pure(a.value) + try applicativeInstance.pure(a.value) catch { case NonFatal(e) => raiseError(e) } @@ -103,7 +103,7 @@ trait ApplicativeError[F[_], E] { */ def fromTry[A](t: Try[A])(implicit ev: Throwable <:< E): F[A] = t match { - case Success(a) => applicative.pure(a) + case Success(a) => applicativeInstance.pure(a) case Failure(e) => raiseError(e) } } diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala index 7e9de095ec..774eae9ab7 100644 --- a/core/src/main/scala/cats/Composed.scala +++ b/core/src/main/scala/cats/Composed.scala @@ -52,7 +52,7 @@ private[cats] trait ComposedAlternative[F[_], G[_]] extends Alternative[λ[α => def F: Alternative[F] def G: Applicative[G] - def applicativeInstance = new ComposedApplicative[F, G] { + def applicativeInstance: Applicative[λ[α => F[G[α]]]] = new ComposedApplicative[F, G] { def F = outer.F.applicativeInstance def G = outer.G } @@ -81,7 +81,7 @@ private[cats] trait ComposedTraverseFilter[F[_], G[_]] extends TraverseFilter[λ def F: Traverse[F] def G: TraverseFilter[G] - def traverseInstance = new ComposedTraverse[F, G] { + def traverseInstance: Traverse[λ[α => F[G[α]]]] = new ComposedTraverse[F, G] { def F = outer.F def G = outer.G.traverseInstance } @@ -94,7 +94,7 @@ private[cats] trait ComposedFunctorFilter[F[_], G[_]] extends FunctorFilter[λ[ def F: Functor[F] def G: FunctorFilter[G] - def functorInstance = new ComposedFunctor[F, G] { + def functorInstance: Functor[λ[α => F[G[α]]]] = new ComposedFunctor[F, G] { def F = outer.F def G = outer.G.functorInstance } diff --git a/core/src/main/scala/cats/FunctorFilter.scala b/core/src/main/scala/cats/FunctorFilter.scala index 19b6cd2133..e9f29ee137 100644 --- a/core/src/main/scala/cats/FunctorFilter.scala +++ b/core/src/main/scala/cats/FunctorFilter.scala @@ -2,7 +2,7 @@ package cats import simulacrum.typeclass -@typeclass trait FunctorFilter[F[_]] { +@typeclass trait FunctorFilter[F[_]] extends Serializable { def functorInstance: Functor[F] /** diff --git a/core/src/main/scala/cats/MonadError.scala b/core/src/main/scala/cats/MonadError.scala index d5bc571b81..c9f6202d47 100644 --- a/core/src/main/scala/cats/MonadError.scala +++ b/core/src/main/scala/cats/MonadError.scala @@ -6,14 +6,14 @@ package cats * This type class allows one to abstract over error-handling monads. */ trait MonadError[F[_], E] extends ApplicativeError[F, E] { - def monad: Monad[F] - def applicative: Applicative[F] = monad + def monadInstance: Monad[F] + def applicativeInstance: Applicative[F] = monadInstance /** * Turns a successful value into an error if it does not satisfy a given predicate. */ def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A] = - monad.flatMap(fa)(a => if (predicate(a)) applicative.pure(a) else raiseError(error)) + monadInstance.flatMap(fa)(a => if (predicate(a)) applicativeInstance.pure(a) else raiseError(error)) } diff --git a/core/src/main/scala/cats/MonadReader.scala b/core/src/main/scala/cats/MonadReader.scala index a1eb9637db..45364ae47a 100644 --- a/core/src/main/scala/cats/MonadReader.scala +++ b/core/src/main/scala/cats/MonadReader.scala @@ -1,8 +1,8 @@ package cats /** A monad that has the ability to read from an environment. */ -trait MonadReader[F[_], R] { - def monad: Monad[F] +trait MonadReader[F[_], R] extends Serializable { + def monadInstance: Monad[F] /** Get the environment */ def ask: F[R] diff --git a/core/src/main/scala/cats/MonadState.scala b/core/src/main/scala/cats/MonadState.scala index 777314ef2e..93c003928b 100644 --- a/core/src/main/scala/cats/MonadState.scala +++ b/core/src/main/scala/cats/MonadState.scala @@ -16,16 +16,16 @@ package cats * } yield r * }}} */ -trait MonadState[F[_], S] { - def monad: Monad[F] +trait MonadState[F[_], S] extends Serializable { + def monadInstance: Monad[F] def get: F[S] def set(s: S): F[Unit] - def modify(f: S => S): F[Unit] = monad.flatMap(get)(s => set(f(s))) + def modify(f: S => S): F[Unit] = monadInstance.flatMap(get)(s => set(f(s))) - def inspect[A](f: S => A): F[A] = monad.map(get)(f) + def inspect[A](f: S => A): F[A] = monadInstance.map(get)(f) } object MonadState { diff --git a/core/src/main/scala/cats/MonadWriter.scala b/core/src/main/scala/cats/MonadWriter.scala index 268104e92f..34bda8d5c3 100644 --- a/core/src/main/scala/cats/MonadWriter.scala +++ b/core/src/main/scala/cats/MonadWriter.scala @@ -1,8 +1,8 @@ package cats /** A monad that support monoidal accumulation (e.g. logging List[String]) */ -trait MonadWriter[F[_], W] { - def monad: Monad[F] +trait MonadWriter[F[_], W] extends Serializable { + def monadInstance: Monad[F] /** Lift a writer action into the effect */ def writer[A](aw: (W, A)): F[A] @@ -18,11 +18,11 @@ trait MonadWriter[F[_], W] { /** Pair the value with an inspection of the accumulator */ def listens[A, B](fa: F[A])(f: W => B): F[(B, A)] = - monad.map(listen(fa)) { case (w, a) => (f(w), a) } + monadInstance.map(listen(fa)) { case (w, a) => (f(w), a) } /** Modify the accumulator */ def censor[A](fa: F[A])(f: W => W): F[A] = - monad.flatMap(listen(fa)) { case (w, a) => writer((f(w), a)) } + monadInstance.flatMap(listen(fa)) { case (w, a) => writer((f(w), a)) } } object MonadWriter { diff --git a/core/src/main/scala/cats/SemigroupK.scala b/core/src/main/scala/cats/SemigroupK.scala index 56ff6456d4..8284e6eb92 100644 --- a/core/src/main/scala/cats/SemigroupK.scala +++ b/core/src/main/scala/cats/SemigroupK.scala @@ -20,7 +20,7 @@ import simulacrum.typeclass * The combination operation just depends on the structure of F, * but not the structure of A. */ -@typeclass trait SemigroupK[F[_]] { self => +@typeclass trait SemigroupK[F[_]] extends Serializable { self => /** * Combine two F[A] values. diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index 904e12b72b..73c44094bd 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -404,7 +404,7 @@ private[data] trait EitherTMonad[F[_], L] extends Monad[EitherT[F, L, ?]] with E private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, ?], L] { outer => implicit val F: Monad[F] - def monad = new EitherTMonad[F, L] { implicit val F = outer.F } + def monadInstance: Monad[EitherT[F, L, ?]] = new EitherTMonad[F, L] { implicit val F = outer.F } def handleErrorWith[A](fea: EitherT[F, L, A])(f: L => EitherT[F, L, A]): EitherT[F, L, A] = EitherT(F.flatMap(fea.value) { case Left(e) => f(e).value @@ -427,7 +427,7 @@ private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L implicit val F: Monad[F] implicit val L: Monoid[L] - implicit def monad = new EitherTMonad[F, L] { + implicit def monadInstance: Monad[EitherT[F, L, ?]] = new EitherTMonad[F, L] { implicit val F = outer.F implicit val L = outer.L } diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 72f08b3c87..aff9b3c8eb 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -191,7 +191,7 @@ private[data] sealed abstract class KleisliInstances3 extends KleisliInstances4 private[data] sealed abstract class KleisliInstances4 { implicit def catsDataMonadReaderForKleisli[F[_]: Monad, A]: MonadReader[Kleisli[F, A, ?], A] = new MonadReader[Kleisli[F, A, ?], A] { - val monad = catsDataMonadForKleisli[F, A] + val monadInstance = catsDataMonadForKleisli[F, A] val ask: Kleisli[F, A, A] = Kleisli(Monad[F].pure) @@ -288,7 +288,8 @@ private trait KleisliApplicativeError[F[_], A, E] extends ApplicativeError[Kleis implicit def F: ApplicativeError[F, E] - def applicative = new KleisliApplicative[F, A] { implicit def F = outer.F.applicative } + def applicativeInstance: Applicative[Kleisli[F, A, ?]] = + new KleisliApplicative[F, A] { implicit def F = outer.F.applicativeInstance } def raiseError[B](e: E): K[B] = Kleisli(_ => F.raiseError(e)) diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index b2d425ca75..eb8d0f2de0 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -157,7 +157,7 @@ private[data] trait NestedFunctor[F[_], G[_]] extends Functor[Nested[F, G, ?]] w private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested[F, G, ?]] { outer => def FG: FunctorFilter[λ[α => F[G[α]]]] - def functorInstance = new NestedFunctor[F, G] { def FG = outer.FG.functorInstance } + def functorInstance: Functor[Nested[F, G, ?]] = new NestedFunctor[F, G] { def FG = outer.FG.functorInstance } override def mapFilter[A, B](fga: Nested[F, G, A])(f: A => Option[B]): Nested[F, G, B] = Nested(FG.mapFilter(fga.value)(f)) @@ -172,11 +172,11 @@ private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested private[data] trait NestedTraverseFilter[F[_], G[_]] extends TraverseFilter[Nested[F, G, ?]] with NestedFunctorFilter[F, G] { outer => override def FG: TraverseFilter[λ[α => F[G[α]]]] - def traverseInstance = new NestedTraverse[F, G] { + def traverseInstance: Traverse[Nested[F, G, ?]] = new NestedTraverse[F, G] { def FG = outer.FG.traverseInstance } - override def functorInstance = traverseInstance + override def functorInstance: Functor[Nested[F, G, ?]] = traverseInstance override def traverseFilter[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[Option[B]]): H[Nested[F, G, B]] = Applicative[H].map(FG.traverseFilter(fga.value)(f))(Nested(_)) @@ -213,7 +213,8 @@ private[data] trait NestedMonoidK[F[_], G[_]] extends MonoidK[Nested[F, G, ?]] w private[data] trait NestedAlternative[F[_], G[_]] extends Alternative[Nested[F, G, ?]] with NestedMonoidK[F, G] { outer => def FG: Alternative[λ[α => F[G[α]]]] - def applicativeInstance = new NestedApplicative[F, G] { def FG = outer.FG.applicativeInstance } + def applicativeInstance: Applicative[Nested[F, G, ?]] = + new NestedApplicative[F, G] { def FG = outer.FG.applicativeInstance } } private[data] trait NestedFoldable[F[_], G[_]] extends Foldable[Nested[F, G, ?]] { diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index c29e6dd11f..e07acc2051 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -121,7 +121,7 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { } implicit def catsDataMonadForOneAnd[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[F, ?]] = { - implicit val monadInstance = monad.monadInstance + implicit def monadInstance = monad.monadInstance new Monad[OneAnd[F, ?]] { override def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] = fa map f diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 2da5bc0f00..9942a5790a 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -250,7 +250,7 @@ private[data] trait OptionTFunctor[F[_]] extends Functor[OptionT[F, ?]] { private[data] trait OptionTFunctorFilter[F[_]] extends FunctorFilter[OptionT[F, ?]] { outer => implicit def F: Functor[F] - def functorInstance = new OptionTFunctor[F] { implicit def F = outer.F } + def functorInstance: Functor[OptionT[F, ?]] = new OptionTFunctor[F] { implicit def F = outer.F } override def mapFilter[A, B](fa: OptionT[F, A])(f: A => Option[B]): OptionT[F, B] = fa.mapFilter(f) @@ -274,10 +274,10 @@ private[data] trait OptionTMonad[F[_]] extends Monad[OptionT[F, ?]] { private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] { outer => def F: MonadError[F, E] - def monad = new OptionTMonad[F] { implicit def F = outer.F.monad } + def monadInstance: Monad[OptionT[F, ?]] = new OptionTMonad[F] { implicit def F = outer.F.monadInstance } override def raiseError[A](e: E): OptionT[F, A] = - OptionT(F.monad.map(F.raiseError[A](e))(Some(_))) + OptionT(F.monadInstance.map(F.raiseError[A](e))(Some(_))) override def handleErrorWith[A](fa: OptionT[F, A])(f: E => OptionT[F, A]): OptionT[F, A] = OptionT(F.handleErrorWith(fa.value)(f(_).value)) @@ -303,7 +303,7 @@ private[data] sealed trait OptionTTraverse[F[_]] extends Traverse[OptionT[F, ?]] private[data] sealed trait OptionTTraverseFilter[F[_]] extends TraverseFilter[OptionT[F, ?]] { outer => implicit def F: Traverse[F] - def traverseInstance = new OptionTTraverse[F] { implicit def F = outer.F } + def traverseInstance: Traverse[OptionT[F, ?]] = new OptionTTraverse[F] { implicit def F = outer.F } def traverseFilter[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[Option[B]]): G[OptionT[F, B]] = fa traverseFilter f diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index ff2af123f6..fd7c1e0d86 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -108,7 +108,7 @@ sealed trait ProdAlternative[F[_], G[_]] extends Alternative[λ[α => Prod[F, G, def F: Alternative[F] def G: Alternative[G] - def applicativeInstance = new ProdApplicative[F, G] { + def applicativeInstance: Applicative[λ[α => Prod[F, G, α]]] = new ProdApplicative[F, G] { def F = outer.F.applicativeInstance def G = outer.G.applicativeInstance } diff --git a/core/src/main/scala/cats/data/StateT.scala b/core/src/main/scala/cats/data/StateT.scala index a47583a90e..ff0e2c9ac3 100644 --- a/core/src/main/scala/cats/data/StateT.scala +++ b/core/src/main/scala/cats/data/StateT.scala @@ -228,7 +228,7 @@ private[data] sealed trait StateTMonad[F[_], S] extends Monad[StateT[F, S, ?]] { private[data] sealed trait StateTMonadState[F[_], S] extends MonadState[StateT[F, S, ?], S] { outer => implicit def F: Monad[F] - def monad = new StateTMonad[F, S] { implicit def F = outer.F } + def monadInstance: Monad[StateT[F, S, ?]] = new StateTMonad[F, S] { implicit def F = outer.F } lazy val get: StateT[F, S, S] = StateT(s => F.pure((s, s))) @@ -250,10 +250,10 @@ private[data] sealed trait StateTSemigroupK[F[_], S] extends SemigroupK[StateT[F } private[data] sealed trait StateTMonadCombine[F[_], S] extends MonadCombine[StateT[F, S, ?]] with StateTSemigroupK[F, S] with StateTTransLift[S] { outer => - implicit def F = G.monadInstance + implicit def F: Monad[F] = G.monadInstance override def G: MonadCombine[F] - def monadInstance = new StateTMonad[F, S] { implicit def F = outer.G.monadInstance } + def monadInstance: Monad[StateT[F, S, ?]] = new StateTMonad[F, S] { implicit def F = outer.G.monadInstance } def empty[A]: StateT[F, S, A] = liftT[F, A](G.empty[A])(F) } diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala index 88af686263..db038b429b 100644 --- a/core/src/main/scala/cats/data/Validated.scala +++ b/core/src/main/scala/cats/data/Validated.scala @@ -282,7 +282,7 @@ private[data] sealed abstract class ValidatedInstances extends ValidatedInstance implicit def catsDataInstancesForValidated[E](implicit E: Semigroup[E]): Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] with Applicative[Validated[E, ?]]= new Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] with Applicative[Validated[E, ?]] { - val applicative = this + val applicativeInstance = this def traverse[F[_]: Applicative, A, B](fa: Validated[E, A])(f: A => F[B]): F[Validated[E, B]] = fa.traverse(f) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index b36b9eafc9..c07a9255a7 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -328,8 +328,8 @@ private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends Applicati implicit def F0: ApplicativeError[F, E] implicit def L0: Monoid[L] - def applicative = new WriterTApplicative[F, L] { - implicit def F0 = outer.F0.applicative + def applicativeInstance: Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { + implicit def F0 = outer.F0.applicativeInstance implicit def L0 = outer.L0 } @@ -342,19 +342,19 @@ private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends Applicati private[data] sealed trait WriterTMonadError[F[_], L, E] extends MonadError[WriterT[F, L, ?], E] with WriterTApplicativeError[F, L, E] { outer => override implicit def F0: MonadError[F, E] - def monad = new WriterTMonad[F, L] { - implicit def F0 = outer.F0.monad + def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { + implicit def F0 = outer.F0.monadInstance implicit def L0 = outer.L0 } - override def applicative = monad + override def applicativeInstance: Applicative[WriterT[F, L, ?]] = monadInstance } private[data] sealed trait WriterTMonadWriter[F[_], L] extends MonadWriter[WriterT[F, L, ?], L] { outer => implicit def F0: Monad[F] implicit def L0: Monoid[L] - def monad = new WriterTMonad[F, L] { + def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { implicit def F0 = outer.F0 implicit def L0 = outer.L0 } @@ -388,7 +388,7 @@ private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[Write override implicit def F0: Alternative[F] implicit def L0: Monoid[L] - def applicativeInstance = new WriterTApplicative[F, L] { + def applicativeInstance: Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { def F0 = outer.F0.applicativeInstance def L0 = outer.L0 } @@ -398,7 +398,7 @@ private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[Write implicit def F0: MonadFilter[F] implicit def L0: Monoid[L] - def monadInstance = new WriterTMonad[F, L] { + def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { def F0 = outer.F0.monadInstance def L0 = outer.L0 } @@ -409,12 +409,12 @@ private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[Write private[data] sealed trait WriterTMonadCombine[F[_], L] extends MonadCombine[WriterT[F, L, ?]] with WriterTAlternative[F, L] { outer => override implicit def F0: MonadCombine[F] - def monadInstance = new WriterTMonad[F, L] { + def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { def F0 = outer.F0.monadInstance def L0 = outer.L0 } - override def applicativeInstance = monadInstance + override def applicativeInstance: Applicative[WriterT[F, L, ?]] = monadInstance } private[data] sealed trait WriterTSemigroup[F[_], L, A] extends Semigroup[WriterT[F, L, A]] { diff --git a/core/src/main/scala/cats/instances/either.scala b/core/src/main/scala/cats/instances/either.scala index 18d67196aa..1957e5b468 100644 --- a/core/src/main/scala/cats/instances/either.scala +++ b/core/src/main/scala/cats/instances/either.scala @@ -30,7 +30,7 @@ trait EitherInstances extends cats.kernel.instances.EitherInstances { // scalastyle:off method.length implicit def catsStdInstancesForEither[A]: MonadError[Either[A, ?], A] with Monad[Either[A, ?]] with Traverse[Either[A, ?]] with RecursiveTailRecM[Either[A, ?]] = new MonadError[Either[A, ?], A] with Monad[Either[A, ?]] with Traverse[Either[A, ?]] with RecursiveTailRecM[Either[A, ?]] { - val monad = this + val monadInstance = this def pure[B](b: B): Either[A, B] = Right(b) diff --git a/core/src/main/scala/cats/instances/function.scala b/core/src/main/scala/cats/instances/function.scala index 14d3ba1248..9ebcfa211b 100644 --- a/core/src/main/scala/cats/instances/function.scala +++ b/core/src/main/scala/cats/instances/function.scala @@ -44,7 +44,7 @@ private[instances] sealed trait Function1Instances { implicit def catsStdMonadReaderForFunction1[T1]: MonadReader[T1 => ?, T1] with Monad[T1 => ?] with RecursiveTailRecM[T1 => ?] = new MonadReader[T1 => ?, T1] with Monad[T1 => ?] with RecursiveTailRecM[T1 => ?] { - val monad = this + val monadInstance = this def pure[R](r: R): T1 => R = _ => r diff --git a/core/src/main/scala/cats/instances/future.scala b/core/src/main/scala/cats/instances/future.scala index a3bf72084e..e766844244 100644 --- a/core/src/main/scala/cats/instances/future.scala +++ b/core/src/main/scala/cats/instances/future.scala @@ -7,7 +7,7 @@ import scala.concurrent.{ExecutionContext, Future} trait FutureInstances extends FutureInstances1 { implicit def catsStdInstancesForFuture(implicit ec: ExecutionContext): MonadError[Future, Throwable] with CoflatMap[Future] with Monad[Future] with RecursiveTailRecM[Future] = new FutureCoflatMap with MonadError[Future, Throwable] with Monad[Future] with RecursiveTailRecM[Future] { - val monad = this + val monadInstance = this def pure[A](x: A): Future[A] = Future.successful(x) diff --git a/core/src/main/scala/cats/instances/option.scala b/core/src/main/scala/cats/instances/option.scala index 93e6400fc0..78a3545dd3 100644 --- a/core/src/main/scala/cats/instances/option.scala +++ b/core/src/main/scala/cats/instances/option.scala @@ -24,7 +24,7 @@ trait OptionInstances extends cats.kernel.instances.OptionInstances with OptionI private[instances] trait OptionInstances0 { implicit val catsStdInstancesForOption: TraverseFilter[Option] with Traverse[Option] with MonadError[Option, Unit] with Monad[Option] with CoflatMap[Option] with RecursiveTailRecM[Option] = new TraverseFilter[Option] with Traverse[Option] with MonadError[Option, Unit] with Monad[Option] with CoflatMap[Option] with RecursiveTailRecM[Option] { - val monad = this + val monadInstance = this val traverseInstance = this def pure[A](x: A): Option[A] = Some(x) diff --git a/core/src/main/scala/cats/instances/try.scala b/core/src/main/scala/cats/instances/try.scala index 7bac78dde3..618a13b529 100644 --- a/core/src/main/scala/cats/instances/try.scala +++ b/core/src/main/scala/cats/instances/try.scala @@ -12,7 +12,7 @@ trait TryInstances extends TryInstances1 { // scalastyle:off method.length implicit def catsStdInstancesForTry: MonadError[Try, Throwable] with CoflatMap[Try] with Traverse[Try] with Monad[Try] with RecursiveTailRecM[Try] = new TryCoflatMap with MonadError[Try, Throwable] with Traverse[Try] with Monad[Try] with RecursiveTailRecM[Try] { - val monad = this + val monadInstance = this def pure[A](x: A): Try[A] = Success(x) diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala index 55884deed4..d29b036e1e 100644 --- a/free/src/main/scala/cats/free/FreeT.scala +++ b/free/src/main/scala/cats/free/FreeT.scala @@ -204,20 +204,20 @@ private[free] sealed trait FreeTInstances0 extends FreeTInstances1 { private[free] sealed trait FreeTInstances extends FreeTInstances0 { implicit def catsFreeMonadErrorForFreeT[S[_], M[_]: RecursiveTailRecM, E](implicit E: MonadError[M, E]): MonadError[FreeT[S, M, ?], E] = new MonadError[FreeT[S, M, ?], E] { - val monad = catsFreeMonadForFreeT[S, M](E.monad) + val monadInstance = catsFreeMonadForFreeT[S, M](E.monadInstance) override def handleErrorWith[A](fa: FreeT[S, M, A])(f: E => FreeT[S, M, A]) = - FreeT.liftT[S, M, FreeT[S, M, A]](E.handleErrorWith(fa.toM(E.monad))(f.andThen(_.toM(E.monad))))(E.monad).flatMap(identity) + FreeT.liftT[S, M, FreeT[S, M, A]](E.handleErrorWith(fa.toM(E.monadInstance))(f.andThen(_.toM(E.monadInstance))))(E.monadInstance).flatMap(identity) override def raiseError[A](e: E) = - FreeT.liftT(E.raiseError[A](e))(E.monad) + FreeT.liftT(E.raiseError[A](e))(E.monadInstance) } implicit def catsFreeMonadStateForFreeT[S[_], M[_], E](implicit M1: MonadState[M, E]): MonadState[FreeT[S, M, ?], E] = new MonadState[FreeT[S, M, ?], E] { - val monad = catsFreeMonadForFreeT[S, M](M1.monad) + val monadInstance = catsFreeMonadForFreeT[S, M](M1.monadInstance) override def get = - FreeT.liftT(M1.get)(M1.monad) + FreeT.liftT(M1.get)(M1.monadInstance) override def set(s: E) = - FreeT.liftT(M1.set(s))(M1.monad) + FreeT.liftT(M1.set(s))(M1.monadInstance) } implicit def catsFreeMonadCombineForFreeT[S[_], M[_]: Alternative]: MonadCombine[FreeT[S, M, ?]] = diff --git a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala index 53ac9bd818..3bdd4b8d0f 100644 --- a/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala +++ b/laws/src/main/scala/cats/laws/ApplicativeErrorLaws.scala @@ -6,7 +6,7 @@ import cats.data.EitherT // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Error/Class/index.html trait ApplicativeErrorLaws[F[_], E] extends ApplicativeLaws[F] { implicit def FE: ApplicativeError[F, E] - implicit def F: Applicative[F] = FE.applicative + implicit def F: Applicative[F] = FE.applicativeInstance def applicativeErrorHandleWith[A](e: E, f: E => F[A]): IsEq[F[A]] = FE.handleErrorWith(FE.raiseError[A](e))(f) <-> f(e) diff --git a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala index 0ea97f4b65..b2de32fc7e 100644 --- a/laws/src/main/scala/cats/laws/MonadErrorLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala @@ -4,7 +4,7 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Error/Class/index.html trait MonadErrorLaws[F[_], E] extends ApplicativeErrorLaws[F, E] with MonadLaws[F] { implicit override def FE: MonadError[F, E] - implicit override def F: Monad[F] = FE.monad + implicit override def F: Monad[F] = FE.monadInstance def monadErrorLeftZero[A, B](e: E, f: A => F[B]): IsEq[F[B]] = F.flatMap(FE.raiseError[A](e))(f) <-> FE.raiseError[B](e) diff --git a/laws/src/main/scala/cats/laws/MonadReaderLaws.scala b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala index 3600433217..713ebfca66 100644 --- a/laws/src/main/scala/cats/laws/MonadReaderLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala @@ -4,7 +4,7 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/Reader/Class/index.html trait MonadReaderLaws[F[_], R] extends MonadLaws[F] { implicit def FR: MonadReader[F, R] - implicit def F: Monad[F] = FR.monad + implicit def F: Monad[F] = FR.monadInstance val monadReaderAskIdempotent: IsEq[F[R]] = F.flatMap(FR.ask)(_ => FR.ask) <-> FR.ask diff --git a/laws/src/main/scala/cats/laws/MonadStateLaws.scala b/laws/src/main/scala/cats/laws/MonadStateLaws.scala index 0f942190b4..30c524e484 100644 --- a/laws/src/main/scala/cats/laws/MonadStateLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadStateLaws.scala @@ -4,7 +4,7 @@ package laws // Taken from http://functorial.com/psc-pages/docs/Control/Monad/State/Class/index.html trait MonadStateLaws[F[_], S] extends MonadLaws[F] { implicit def FS: MonadState[F, S] - implicit def F: Monad[F] = FS.monad + implicit def F: Monad[F] = FS.monadInstance val monadStateGetIdempotent: IsEq[F[S]] = F.flatMap(FS.get)(_ => FS.get) <-> FS.get diff --git a/laws/src/main/scala/cats/laws/MonadWriterLaws.scala b/laws/src/main/scala/cats/laws/MonadWriterLaws.scala index abdb44c807..389cfa2846 100644 --- a/laws/src/main/scala/cats/laws/MonadWriterLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadWriterLaws.scala @@ -3,7 +3,7 @@ package laws trait MonadWriterLaws[F[_], W] extends MonadLaws[F] { implicit def FW: MonadWriter[F, W] - implicit def F: Monad[F] = FW.monad + implicit def F: Monad[F] = FW.monadInstance def monadWriterWriterPure[A](a: A)(implicit W: Monoid[W]): IsEq[F[A]] = FW.writer((W.empty, a)) <-> F.pure(a) From 8109046fe6a670ce93631db6b6f0821e35f827e1 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 22:39:46 -0700 Subject: [PATCH 08/12] Fix NPE and docs --- core/src/main/scala/cats/FunctorFilter.scala | 2 +- core/src/main/scala/cats/TraverseFilter.scala | 4 +- core/src/main/scala/cats/data/OneAnd.scala | 2 +- docs/src/main/tut/freemonad.md | 4 +- .../test/scala/cats/tests/ListWrapper.scala | 46 +++++++++---------- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/core/src/main/scala/cats/FunctorFilter.scala b/core/src/main/scala/cats/FunctorFilter.scala index e9f29ee137..085eed64d4 100644 --- a/core/src/main/scala/cats/FunctorFilter.scala +++ b/core/src/main/scala/cats/FunctorFilter.scala @@ -6,7 +6,7 @@ import simulacrum.typeclass def functorInstance: Functor[F] /** - * A combined [[map]] and [[filter]]. Filtering is handled via `Option` + * A combined `map` and [[filter]]. Filtering is handled via `Option` * instead of `Boolean` such that the output type `B` can be different than * the input type `A`. * diff --git a/core/src/main/scala/cats/TraverseFilter.scala b/core/src/main/scala/cats/TraverseFilter.scala index 52efa2a05e..fa3e6c2718 100644 --- a/core/src/main/scala/cats/TraverseFilter.scala +++ b/core/src/main/scala/cats/TraverseFilter.scala @@ -4,7 +4,7 @@ import simulacrum.typeclass /** * `TraverseFilter`, also known as `Witherable`, represents list-like structures - * that can essentially have a [[traverse]] and a [[filter]] applied as a single + * that can essentially have a `traverse` and a [[filter]] applied as a single * combined operation ([[traverseFilter]]). * * Must obey the laws defined in cats.laws.TraverseFilterLaws. @@ -16,7 +16,7 @@ import simulacrum.typeclass def functorInstance: Functor[F] = traverseInstance /** - * A combined [[traverse]] and [[filter]]. Filtering is handled via `Option` + * A combined `traverse` and [[filter]]. Filtering is handled via `Option` * instead of `Boolean` such that the output type `B` can be different than * the input type `A`. * diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index e07acc2051..c29e6dd11f 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -121,7 +121,7 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority2 { } implicit def catsDataMonadForOneAnd[F[_]](implicit monad: MonadCombine[F]): Monad[OneAnd[F, ?]] = { - implicit def monadInstance = monad.monadInstance + implicit val monadInstance = monad.monadInstance new Monad[OneAnd[F, ?]] { override def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] = fa map f diff --git a/docs/src/main/tut/freemonad.md b/docs/src/main/tut/freemonad.md index f88afc996d..ab84d1f7f9 100644 --- a/docs/src/main/tut/freemonad.md +++ b/docs/src/main/tut/freemonad.md @@ -521,9 +521,9 @@ type TeletypeT[M[_], A] = FreeT[Teletype, M, A] type Log = List[String] /** Smart constructors, notice we are abstracting over any MonadState instance - * to potentially support other types beside State + * to potentially support other types beside State */ -class TeletypeOps[M[_]](implicit MS : MonadState[M, Log]) { +class TeletypeOps[M[_]](implicit MS : MonadState[M, Log], M: Monad[M]) { def writeLine(line : String) : TeletypeT[M, Unit] = FreeT.liftF[Teletype, M, Unit](WriteLine(line)) def readLine(prompt : String) : TeletypeT[M, String] = diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index b68cb788c1..b6b3d587d9 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -44,17 +44,6 @@ object ListWrapper { def eqv[A : Eq]: Eq[ListWrapper[A]] = Eq[List[A]].on[ListWrapper[A]](_.list) - val traverseFilter: TraverseFilter[ListWrapper] = { - val F = TraverseFilter[List] - - new TraverseFilter[ListWrapper] { - val traverseInstance = traverse - def traverseFilter[G[_], A, B](fa: ListWrapper[A])(f: A => G[Option[B]])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { - G0.map(F.traverseFilter(fa.list)(f))(ListWrapper.apply) - } - } - } - val traverse: Traverse[ListWrapper] = new Traverse[ListWrapper] { val F = Traverse[List] @@ -66,6 +55,17 @@ object ListWrapper { F.foldRight(fa.list, lb)(f) } + val traverseFilter: TraverseFilter[ListWrapper] = { + val F = TraverseFilter[List] + + new TraverseFilter[ListWrapper] { + val traverseInstance = traverse + def traverseFilter[G[_], A, B](fa: ListWrapper[A])(f: A => G[Option[B]])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { + G0.map(F.traverseFilter(fa.list)(f))(ListWrapper.apply) + } + } + } + val foldable: Foldable[ListWrapper] = traverse val functor: Functor[ListWrapper] = traverse @@ -82,6 +82,18 @@ object ListWrapper { def semigroup[A]: Semigroup[ListWrapper[A]] = semigroupK.algebra[A] + val monad: Monad[ListWrapper] = new Monad[ListWrapper] { + val M = Monad[List] + + def pure[A](x: A): ListWrapper[A] = ListWrapper(M.pure(x)) + + def flatMap[A, B](fa: ListWrapper[A])(f: A => ListWrapper[B]): ListWrapper[B] = + ListWrapper(M.flatMap(fa.list)(a => f(a).list)) + + def tailRecM[A, B](a: A)(f: A => ListWrapper[Either[A,B]]): ListWrapper[B] = + ListWrapper(M.tailRecM(a)(a => f(a).list)) + } + val monadCombine: MonadCombine[ListWrapper] = { val M = MonadCombine[List] @@ -95,18 +107,6 @@ object ListWrapper { } } - val monad: Monad[ListWrapper] = new Monad[ListWrapper] { - val M = Monad[List] - - def pure[A](x: A): ListWrapper[A] = ListWrapper(M.pure(x)) - - def flatMap[A, B](fa: ListWrapper[A])(f: A => ListWrapper[B]): ListWrapper[B] = - ListWrapper(M.flatMap(fa.list)(a => f(a).list)) - - def tailRecM[A, B](a: A)(f: A => ListWrapper[Either[A,B]]): ListWrapper[B] = - ListWrapper(M.tailRecM(a)(a => f(a).list)) - } - val applicative: Applicative[ListWrapper] = monad /** apply is taken due to ListWrapper being a case class */ From 548c5d88892e551fe70f4288bb5257c74225735f Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 22:54:30 -0700 Subject: [PATCH 09/12] Make superclass instances vals where possible --- core/src/main/scala/cats/Composed.scala | 6 ++--- core/src/main/scala/cats/data/EitherT.scala | 24 +++++++++---------- core/src/main/scala/cats/data/Kleisli.scala | 2 +- core/src/main/scala/cats/data/Nested.scala | 8 +++---- core/src/main/scala/cats/data/OptionT.scala | 6 ++--- core/src/main/scala/cats/data/Prod.scala | 2 +- core/src/main/scala/cats/data/StateT.scala | 4 ++-- core/src/main/scala/cats/data/WriterT.scala | 16 ++++++------- .../scala/cats/tests/ApplicativeTests.scala | 2 +- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala index 774eae9ab7..9401e13a30 100644 --- a/core/src/main/scala/cats/Composed.scala +++ b/core/src/main/scala/cats/Composed.scala @@ -52,7 +52,7 @@ private[cats] trait ComposedAlternative[F[_], G[_]] extends Alternative[λ[α => def F: Alternative[F] def G: Applicative[G] - def applicativeInstance: Applicative[λ[α => F[G[α]]]] = new ComposedApplicative[F, G] { + val applicativeInstance: Applicative[λ[α => F[G[α]]]] = new ComposedApplicative[F, G] { def F = outer.F.applicativeInstance def G = outer.G } @@ -81,7 +81,7 @@ private[cats] trait ComposedTraverseFilter[F[_], G[_]] extends TraverseFilter[λ def F: Traverse[F] def G: TraverseFilter[G] - def traverseInstance: Traverse[λ[α => F[G[α]]]] = new ComposedTraverse[F, G] { + val traverseInstance: Traverse[λ[α => F[G[α]]]] = new ComposedTraverse[F, G] { def F = outer.F def G = outer.G.traverseInstance } @@ -94,7 +94,7 @@ private[cats] trait ComposedFunctorFilter[F[_], G[_]] extends FunctorFilter[λ[ def F: Functor[F] def G: FunctorFilter[G] - def functorInstance: Functor[λ[α => F[G[α]]]] = new ComposedFunctor[F, G] { + val functorInstance: Functor[λ[α => F[G[α]]]] = new ComposedFunctor[F, G] { def F = outer.F def G = outer.G.functorInstance } diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index 73c44094bd..468bae35c8 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -366,18 +366,18 @@ private[data] abstract class EitherTInstances3 { } private[data] trait EitherTSemigroup[F[_], L, A] extends Semigroup[EitherT[F, L, A]] { - implicit val F0: Semigroup[F[Either[L, A]]] + implicit def F0: Semigroup[F[Either[L, A]]] def combine(x: EitherT[F, L , A], y: EitherT[F, L , A]): EitherT[F, L , A] = EitherT(F0.combine(x.value, y.value)) } private[data] trait EitherTMonoid[F[_], L, A] extends Monoid[EitherT[F, L, A]] with EitherTSemigroup[F, L, A] { - implicit val F0: Monoid[F[Either[L, A]]] + implicit def F0: Monoid[F[Either[L, A]]] def empty: EitherT[F, L, A] = EitherT(F0.empty) } private[data] trait EitherTSemigroupK[F[_], L] extends SemigroupK[EitherT[F, L, ?]] { - implicit val F: Monad[F] + implicit def F: Monad[F] def combineK[A](x: EitherT[F, L, A], y: EitherT[F, L, A]): EitherT[F, L, A] = EitherT(F.flatMap(x.value) { case l @ Left(_) => y.value @@ -386,12 +386,12 @@ private[data] trait EitherTSemigroupK[F[_], L] extends SemigroupK[EitherT[F, L, } private[data] trait EitherTFunctor[F[_], L] extends Functor[EitherT[F, L, ?]] { - implicit val F: Functor[F] + implicit def F: Functor[F] override def map[A, B](fa: EitherT[F, L, A])(f: A => B): EitherT[F, L, B] = fa map f } private[data] trait EitherTMonad[F[_], L] extends Monad[EitherT[F, L, ?]] with EitherTFunctor[F, L] { - implicit val F: Monad[F] + implicit def F: Monad[F] def pure[A](a: A): EitherT[F, L, A] = EitherT(F.pure(Either.right(a))) def flatMap[A, B](fa: EitherT[F, L, A])(f: A => EitherT[F, L, B]): EitherT[F, L, B] = fa flatMap f def tailRecM[A, B](a: A)(f: A => EitherT[F, L, Either[A, B]]): EitherT[F, L, B] = @@ -403,8 +403,8 @@ private[data] trait EitherTMonad[F[_], L] extends Monad[EitherT[F, L, ?]] with E } private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, ?], L] { outer => - implicit val F: Monad[F] - def monadInstance: Monad[EitherT[F, L, ?]] = new EitherTMonad[F, L] { implicit val F = outer.F } + implicit def F: Monad[F] + val monadInstance: Monad[EitherT[F, L, ?]] = new EitherTMonad[F, L] { implicit def F = outer.F } def handleErrorWith[A](fea: EitherT[F, L, A])(f: L => EitherT[F, L, A]): EitherT[F, L, A] = EitherT(F.flatMap(fea.value) { case Left(e) => f(e).value @@ -424,12 +424,12 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, } private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] { outer => - implicit val F: Monad[F] - implicit val L: Monoid[L] + implicit def F: Monad[F] + implicit def L: Monoid[L] - implicit def monadInstance: Monad[EitherT[F, L, ?]] = new EitherTMonad[F, L] { - implicit val F = outer.F - implicit val L = outer.L + implicit val monadInstance: Monad[EitherT[F, L, ?]] = new EitherTMonad[F, L] { + implicit def F = outer.F + implicit def L = outer.L } def empty[A]: EitherT[F, L, A] = EitherT(F.pure(Either.left(L.empty))) diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index aff9b3c8eb..c06363e4d7 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -288,7 +288,7 @@ private trait KleisliApplicativeError[F[_], A, E] extends ApplicativeError[Kleis implicit def F: ApplicativeError[F, E] - def applicativeInstance: Applicative[Kleisli[F, A, ?]] = + val applicativeInstance: Applicative[Kleisli[F, A, ?]] = new KleisliApplicative[F, A] { implicit def F = outer.F.applicativeInstance } def raiseError[B](e: E): K[B] = Kleisli(_ => F.raiseError(e)) diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index eb8d0f2de0..3813b667b4 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -157,7 +157,7 @@ private[data] trait NestedFunctor[F[_], G[_]] extends Functor[Nested[F, G, ?]] w private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested[F, G, ?]] { outer => def FG: FunctorFilter[λ[α => F[G[α]]]] - def functorInstance: Functor[Nested[F, G, ?]] = new NestedFunctor[F, G] { def FG = outer.FG.functorInstance } + val functorInstance: Functor[Nested[F, G, ?]] = new NestedFunctor[F, G] { def FG = outer.FG.functorInstance } override def mapFilter[A, B](fga: Nested[F, G, A])(f: A => Option[B]): Nested[F, G, B] = Nested(FG.mapFilter(fga.value)(f)) @@ -172,11 +172,11 @@ private[data] trait NestedFunctorFilter[F[_], G[_]] extends FunctorFilter[Nested private[data] trait NestedTraverseFilter[F[_], G[_]] extends TraverseFilter[Nested[F, G, ?]] with NestedFunctorFilter[F, G] { outer => override def FG: TraverseFilter[λ[α => F[G[α]]]] - def traverseInstance: Traverse[Nested[F, G, ?]] = new NestedTraverse[F, G] { + val traverseInstance: Traverse[Nested[F, G, ?]] = new NestedTraverse[F, G] { def FG = outer.FG.traverseInstance } - override def functorInstance: Functor[Nested[F, G, ?]] = traverseInstance + override val functorInstance: Functor[Nested[F, G, ?]] = traverseInstance override def traverseFilter[H[_]: Applicative, A, B](fga: Nested[F, G, A])(f: A => H[Option[B]]): H[Nested[F, G, B]] = Applicative[H].map(FG.traverseFilter(fga.value)(f))(Nested(_)) @@ -213,7 +213,7 @@ private[data] trait NestedMonoidK[F[_], G[_]] extends MonoidK[Nested[F, G, ?]] w private[data] trait NestedAlternative[F[_], G[_]] extends Alternative[Nested[F, G, ?]] with NestedMonoidK[F, G] { outer => def FG: Alternative[λ[α => F[G[α]]]] - def applicativeInstance: Applicative[Nested[F, G, ?]] = + val applicativeInstance: Applicative[Nested[F, G, ?]] = new NestedApplicative[F, G] { def FG = outer.FG.applicativeInstance } } diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 9942a5790a..1273b727cf 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -250,7 +250,7 @@ private[data] trait OptionTFunctor[F[_]] extends Functor[OptionT[F, ?]] { private[data] trait OptionTFunctorFilter[F[_]] extends FunctorFilter[OptionT[F, ?]] { outer => implicit def F: Functor[F] - def functorInstance: Functor[OptionT[F, ?]] = new OptionTFunctor[F] { implicit def F = outer.F } + val functorInstance: Functor[OptionT[F, ?]] = new OptionTFunctor[F] { implicit def F = outer.F } override def mapFilter[A, B](fa: OptionT[F, A])(f: A => Option[B]): OptionT[F, B] = fa.mapFilter(f) @@ -274,7 +274,7 @@ private[data] trait OptionTMonad[F[_]] extends Monad[OptionT[F, ?]] { private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] { outer => def F: MonadError[F, E] - def monadInstance: Monad[OptionT[F, ?]] = new OptionTMonad[F] { implicit def F = outer.F.monadInstance } + val monadInstance: Monad[OptionT[F, ?]] = new OptionTMonad[F] { implicit def F = outer.F.monadInstance } override def raiseError[A](e: E): OptionT[F, A] = OptionT(F.monadInstance.map(F.raiseError[A](e))(Some(_))) @@ -303,7 +303,7 @@ private[data] sealed trait OptionTTraverse[F[_]] extends Traverse[OptionT[F, ?]] private[data] sealed trait OptionTTraverseFilter[F[_]] extends TraverseFilter[OptionT[F, ?]] { outer => implicit def F: Traverse[F] - def traverseInstance: Traverse[OptionT[F, ?]] = new OptionTTraverse[F] { implicit def F = outer.F } + val traverseInstance: Traverse[OptionT[F, ?]] = new OptionTTraverse[F] { implicit def F = outer.F } def traverseFilter[G[_]: Applicative, A, B](fa: OptionT[F, A])(f: A => G[Option[B]]): G[OptionT[F, B]] = fa traverseFilter f diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index fd7c1e0d86..2bc5923ac0 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -108,7 +108,7 @@ sealed trait ProdAlternative[F[_], G[_]] extends Alternative[λ[α => Prod[F, G, def F: Alternative[F] def G: Alternative[G] - def applicativeInstance: Applicative[λ[α => Prod[F, G, α]]] = new ProdApplicative[F, G] { + val applicativeInstance: Applicative[λ[α => Prod[F, G, α]]] = new ProdApplicative[F, G] { def F = outer.F.applicativeInstance def G = outer.G.applicativeInstance } diff --git a/core/src/main/scala/cats/data/StateT.scala b/core/src/main/scala/cats/data/StateT.scala index ff0e2c9ac3..f6f72be524 100644 --- a/core/src/main/scala/cats/data/StateT.scala +++ b/core/src/main/scala/cats/data/StateT.scala @@ -228,7 +228,7 @@ private[data] sealed trait StateTMonad[F[_], S] extends Monad[StateT[F, S, ?]] { private[data] sealed trait StateTMonadState[F[_], S] extends MonadState[StateT[F, S, ?], S] { outer => implicit def F: Monad[F] - def monadInstance: Monad[StateT[F, S, ?]] = new StateTMonad[F, S] { implicit def F = outer.F } + val monadInstance: Monad[StateT[F, S, ?]] = new StateTMonad[F, S] { implicit def F = outer.F } lazy val get: StateT[F, S, S] = StateT(s => F.pure((s, s))) @@ -253,7 +253,7 @@ private[data] sealed trait StateTMonadCombine[F[_], S] extends MonadCombine[Stat implicit def F: Monad[F] = G.monadInstance override def G: MonadCombine[F] - def monadInstance: Monad[StateT[F, S, ?]] = new StateTMonad[F, S] { implicit def F = outer.G.monadInstance } + val monadInstance: Monad[StateT[F, S, ?]] = new StateTMonad[F, S] { implicit def F = outer.G.monadInstance } def empty[A]: StateT[F, S, A] = liftT[F, A](G.empty[A])(F) } diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index c07a9255a7..70aac926f1 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -328,7 +328,7 @@ private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends Applicati implicit def F0: ApplicativeError[F, E] implicit def L0: Monoid[L] - def applicativeInstance: Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { + val applicativeInstance: Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { implicit def F0 = outer.F0.applicativeInstance implicit def L0 = outer.L0 } @@ -342,19 +342,19 @@ private[data] sealed trait WriterTApplicativeError[F[_], L, E] extends Applicati private[data] sealed trait WriterTMonadError[F[_], L, E] extends MonadError[WriterT[F, L, ?], E] with WriterTApplicativeError[F, L, E] { outer => override implicit def F0: MonadError[F, E] - def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { + val monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { implicit def F0 = outer.F0.monadInstance implicit def L0 = outer.L0 } - override def applicativeInstance: Applicative[WriterT[F, L, ?]] = monadInstance + override val applicativeInstance: Applicative[WriterT[F, L, ?]] = monadInstance } private[data] sealed trait WriterTMonadWriter[F[_], L] extends MonadWriter[WriterT[F, L, ?], L] { outer => implicit def F0: Monad[F] implicit def L0: Monoid[L] - def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { + val monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { implicit def F0 = outer.F0 implicit def L0 = outer.L0 } @@ -388,7 +388,7 @@ private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[Write override implicit def F0: Alternative[F] implicit def L0: Monoid[L] - def applicativeInstance: Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { + val applicativeInstance: Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { def F0 = outer.F0.applicativeInstance def L0 = outer.L0 } @@ -398,7 +398,7 @@ private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[Write implicit def F0: MonadFilter[F] implicit def L0: Monoid[L] - def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { + val monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { def F0 = outer.F0.monadInstance def L0 = outer.L0 } @@ -409,12 +409,12 @@ private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[Write private[data] sealed trait WriterTMonadCombine[F[_], L] extends MonadCombine[WriterT[F, L, ?]] with WriterTAlternative[F, L] { outer => override implicit def F0: MonadCombine[F] - def monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { + val monadInstance: Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { def F0 = outer.F0.monadInstance def L0 = outer.L0 } - override def applicativeInstance: Applicative[WriterT[F, L, ?]] = monadInstance + override val applicativeInstance: Applicative[WriterT[F, L, ?]] = monadInstance } private[data] sealed trait WriterTSemigroup[F[_], L, A] extends Semigroup[WriterT[F, L, A]] { diff --git a/tests/src/test/scala/cats/tests/ApplicativeTests.scala b/tests/src/test/scala/cats/tests/ApplicativeTests.scala index f93ac4e318..5271d0796e 100644 --- a/tests/src/test/scala/cats/tests/ApplicativeTests.scala +++ b/tests/src/test/scala/cats/tests/ApplicativeTests.scala @@ -13,4 +13,4 @@ class ApplicativeCheck extends CatsSuite { A.replicateA(5, fa) should === (Some(List(1,1,1,1,1))) } -} \ No newline at end of file +} From 374ee9cb17835ab4b3d7e3686dff0c9a0cd7c095 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 23:03:28 -0700 Subject: [PATCH 10/12] Add MTL usage test --- .../src/test/scala/cats/tests/MTLTests.scala | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/src/test/scala/cats/tests/MTLTests.scala diff --git a/tests/src/test/scala/cats/tests/MTLTests.scala b/tests/src/test/scala/cats/tests/MTLTests.scala new file mode 100644 index 0000000000..cdcb876a74 --- /dev/null +++ b/tests/src/test/scala/cats/tests/MTLTests.scala @@ -0,0 +1,34 @@ +package cats +package tests + +import cats.instances.AllInstances +import cats.syntax.AllSyntax + +/** + * Test that MTL usage works. Successful compilation is all + * that's needed here. + */ +object MTLTests extends AllInstances with AllSyntax { + def app[F[_], E, R, S, W](implicit + F0: Monad[F], + F1: MonadFilter[F], + F2: TraverseFilter[F], + F3: MonadError[F, E], + F4: MonadReader[F, R], + F5: MonadState[F, S], + F6: MonadWriter[F, W] + ): F[Unit] = { + val x = F4.ask + + /** monads work */ + val a = for { + _ <- x + _ <- x + } yield 42 + + /** traverse filter */ + val b = a.traverseFilter(_ => List.empty[Option[Double]]) + + ().pure[F] + } +} From 25b075e6536b7ca9ea47adb2830242a1a9c7f05f Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sat, 17 Sep 2016 23:55:11 -0700 Subject: [PATCH 11/12] Fix tut --- docs/src/main/tut/freemonad.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/src/main/tut/freemonad.md b/docs/src/main/tut/freemonad.md index ab84d1f7f9..969bb735e8 100644 --- a/docs/src/main/tut/freemonad.md +++ b/docs/src/main/tut/freemonad.md @@ -353,7 +353,7 @@ object DataSource { ADTs are now easily composed and trivially intertwined inside monadic contexts. ```tut:silent -def program(implicit I : Interacts[CatsApp], D : DataSource[CatsApp]): Free[CatsApp, Unit] = { +def program(implicit I: Interacts[CatsApp], D: DataSource[CatsApp]): Free[CatsApp, Unit] = { import I._, D._ @@ -495,9 +495,9 @@ right-associated structure not subject to quadratic complexity. ## FreeT -Often times we want to interleave the syntax tree when building a Free monad -with some other effect not declared as part of the ADT. -FreeT solves this problem by allowing us to mix building steps of the AST +Often times we want to interleave the syntax tree when building a Free monad +with some other effect not declared as part of the ADT. +FreeT solves this problem by allowing us to mix building steps of the AST with calling action in other base monad. In the following example a basic console application is shown. @@ -514,8 +514,8 @@ import cats.data._ /* A base ADT for the user interaction without state semantics */ sealed abstract class Teletype[A] extends Product with Serializable -final case class WriteLine(line : String) extends Teletype[Unit] -final case class ReadLine(prompt : String) extends Teletype[String] +final case class WriteLine(line: String) extends Teletype[Unit] +final case class ReadLine(prompt: String) extends Teletype[String] type TeletypeT[M[_], A] = FreeT[Teletype, M, A] type Log = List[String] @@ -523,31 +523,31 @@ type Log = List[String] /** Smart constructors, notice we are abstracting over any MonadState instance * to potentially support other types beside State */ -class TeletypeOps[M[_]](implicit MS : MonadState[M, Log], M: Monad[M]) { - def writeLine(line : String) : TeletypeT[M, Unit] = +class TeletypeOps[M[_]](implicit MS: MonadState[M, Log], M: Monad[M]) { + def writeLine(line: String): TeletypeT[M, Unit] = FreeT.liftF[Teletype, M, Unit](WriteLine(line)) - def readLine(prompt : String) : TeletypeT[M, String] = + def readLine(prompt: String): TeletypeT[M, String] = FreeT.liftF[Teletype, M, String](ReadLine(prompt)) - def log(s : String) : TeletypeT[M, Unit] = + def log(s: String): TeletypeT[M, Unit] = FreeT.liftT[Teletype, M, Unit](MS.modify(s :: _)) } object TeletypeOps { - implicit def teleTypeOpsInstance[M[_]](implicit MS : MonadState[M, Log]) : TeletypeOps[M] = new TeletypeOps + implicit def teleTypeOpsInstance[M[_]](implicit MS: MonadState[M, Log], M: Monad[M]): TeletypeOps[M] = new TeletypeOps } type TeletypeState[A] = State[List[String], A] -def program(implicit TO : TeletypeOps[TeletypeState]) : TeletypeT[TeletypeState, Unit] = { +def program(implicit TO: TeletypeOps[TeletypeState]): TeletypeT[TeletypeState, Unit] = { for { userSaid <- TO.readLine("what's up?!") - _ <- TO.log(s"user said : $userSaid") + _ <- TO.log(s"user said: $userSaid") _ <- TO.writeLine("thanks, see you soon!") - } yield () + } yield () } def interpreter = new (Teletype ~> TeletypeState) { - def apply[A](fa : Teletype[A]) : TeletypeState[A] = { + def apply[A](fa: Teletype[A]): TeletypeState[A] = { fa match { case ReadLine(prompt) => println(prompt) From 9c639b30fab9b20453a6d94b18953e2f871482a8 Mon Sep 17 00:00:00 2001 From: Adelbert Chang Date: Sun, 18 Sep 2016 00:51:01 -0700 Subject: [PATCH 12/12] FreeT monad instance val --- free/src/main/scala/cats/free/FreeT.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala index d29b036e1e..120dad3852 100644 --- a/free/src/main/scala/cats/free/FreeT.scala +++ b/free/src/main/scala/cats/free/FreeT.scala @@ -225,7 +225,7 @@ private[free] sealed trait FreeTInstances extends FreeTInstances0 { override def M = Alternative[M].applicativeInstance override def M1 = implicitly - def monadInstance = catsFreeMonadForFreeT[S, M](Alternative[M].applicativeInstance) + val monadInstance = catsFreeMonadForFreeT[S, M](Alternative[M].applicativeInstance) override def empty[A] = FreeT.liftT[S, M, A](MonoidK[M].empty[A])(M) }