diff --git a/README.md b/README.md index 528887fe8e7..7f25652f0fb 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ There are many projects that integrate with Cats: * [Dogs](https://github.com/stew/dogs): pure functional collections and data structures. * [Fetch](https://github.com/47deg/fetch): efficient data access to heterogeneous data sources. * [Frameless](https://github.com/adelbertc/frameless): Expressive types for Spark. + * [Freestyle](https://github.com/47deg/freestyle): pure functional framework for Free and Tagless Final apps & libs. * [FS2](https://github.com/functional-streams-for-scala): compositional, streaming I/O library * [Kittens](https://github.com/milessabin/kittens): automatically derived type class instances. * [Monix](https://github.com/monixio/monix): high-performance library for composing asynchronous and event-based programs. diff --git a/build.sbt b/build.sbt index 6d09ffeb94c..fe5c68015e6 100644 --- a/build.sbt +++ b/build.sbt @@ -36,7 +36,7 @@ lazy val commonSettings = Seq( Resolver.sonatypeRepo("snapshots") ), libraryDependencies ++= Seq( - "com.github.mpilquist" %%% "simulacrum" % "0.10.0", + "com.github.mpilquist" %%% "simulacrum" % "0.10.0" % "compile-time", "org.typelevel" %%% "machinist" % "0.6.1", compilerPlugin("org.scalamacros" %% "paradise" % "2.1.0" cross CrossVersion.patch), compilerPlugin("org.spire-math" %% "kind-projector" % "0.9.3") @@ -45,7 +45,9 @@ lazy val commonSettings = Seq( parallelExecution in Test := false, scalacOptions in (Compile, doc) := (scalacOptions in (Compile, doc)).value.filter(_ != "-Xfatal-warnings"), // workaround for https://github.com/scalastyle/scalastyle-sbt-plugin/issues/47 - scalastyleSources in Compile ++= (unmanagedSourceDirectories in Compile).value + scalastyleSources in Compile ++= (unmanagedSourceDirectories in Compile).value, + ivyConfigurations += config("compile-time").hide, + unmanagedClasspath in Compile ++= update.value.select(configurationFilter("compile-time")) ) ++ warnUnusedImport ++ update2_12 lazy val tagName = Def.setting{ @@ -91,8 +93,8 @@ lazy val includeGeneratedSrc: Setting[_] = { lazy val catsSettings = commonSettings ++ publishSettings ++ scoverageSettings ++ javadocSettings lazy val scalaCheckVersion = "1.13.4" -lazy val scalaTestVersion = "3.0.0" -lazy val disciplineVersion = "0.7.2" +lazy val scalaTestVersion = "3.0.1" +lazy val disciplineVersion = "0.7.3" lazy val disciplineDependencies = Seq( libraryDependencies += "org.scalacheck" %%% "scalacheck" % scalaCheckVersion, diff --git a/core/src/main/scala/cats/Foldable.scala b/core/src/main/scala/cats/Foldable.scala index 46fac29fea2..641ef1379dc 100644 --- a/core/src/main/scala/cats/Foldable.scala +++ b/core/src/main/scala/cats/Foldable.scala @@ -231,30 +231,6 @@ import simulacrum.typeclass G.map2Eval(f(a), acc) { (_, _) => () } }.value - /** - * Behaves like traverse_, but uses [[Unapply]] to find the - * [[Applicative]] instance for `G` - used when `G` is a - * type constructor with two or more parameters such as [[scala.util.Either]] - * - * {{{ - * scala> import cats.implicits._ - * scala> def parseInt(s: String): Either[String, Int] = - * | try { Right(s.toInt) } - * | catch { case _: NumberFormatException => Left("boo") } - * scala> val F = Foldable[List] - * scala> F.traverseU_(List("333", "444"))(parseInt) - * res0: Either[String, Unit] = Right(()) - * scala> F.traverseU_(List("333", "zzz"))(parseInt) - * res1: Either[String, Unit] = Left(boo) - * }}} - * - * Note that using `traverse_` instead of `traverseU_` would not compile without - * explicitly passing in the type parameters - the type checker has trouble - * inferring the appropriate instance. - */ - def traverseU_[A, GB](fa: F[A])(f: A => GB)(implicit U: Unapply[Applicative, GB]): U.M[Unit] = - traverse_(fa)(f.andThen(U.subst))(U.TC) - /** * Sequence `F[G[A]]` using `Applicative[G]`. * @@ -275,27 +251,6 @@ import simulacrum.typeclass def sequence_[G[_]: Applicative, A](fga: F[G[A]]): G[Unit] = traverse_(fga)(identity) - /** - * Behaves like sequence_, but uses [[Unapply]] to find the - * [[Applicative]] instance for `G` - used when `G` is a - * type constructor with two or more parameters such as [[scala.util.Either]] - * - * {{{ - * scala> import cats.implicits._ - * scala> val F = Foldable[List] - * scala> F.sequenceU_(List(Either.right[String, Int](333), Right(444))) - * res0: Either[String, Unit] = Right(()) - * scala> F.sequenceU_(List(Either.right[String, Int](333), Left("boo"))) - * res1: Either[String, Unit] = Left(boo) - * }}} - * - * Note that using `sequence_` instead of `sequenceU_` would not compile without - * explicitly passing in the type parameters - the type checker has trouble - * inferring the appropriate instance. - */ - def sequenceU_[GA](fa: F[GA])(implicit U: Unapply[Applicative, GA]): U.M[Unit] = - traverseU_(fa)(identity) - /** * Fold implemented using the given `MonoidK[G]` instance. * diff --git a/core/src/main/scala/cats/Inject.scala b/core/src/main/scala/cats/InjectK.scala similarity index 52% rename from core/src/main/scala/cats/Inject.scala rename to core/src/main/scala/cats/InjectK.scala index db6e76e2181..6176204259c 100644 --- a/core/src/main/scala/cats/Inject.scala +++ b/core/src/main/scala/cats/InjectK.scala @@ -4,11 +4,12 @@ import cats.arrow.FunctionK import cats.data.EitherK /** - * Inject type class as described in "Data types a la carte" (Swierstra 2008). + * The injection type class as described in "Data types a la carte" + * (Swierstra 2008). * * @see [[http://www.staff.science.uu.nl/~swier004/publications/2008-jfp.pdf]] */ -sealed abstract class Inject[F[_], G[_]] { +sealed abstract class InjectK[F[_], G[_]] { def inj: FunctionK[F, G] def prj: FunctionK[G, λ[α => Option[F[α]]]] @@ -18,29 +19,29 @@ sealed abstract class Inject[F[_], G[_]] { def unapply[A](ga: G[A]): Option[F[A]] = prj(ga) } -private[cats] sealed abstract class InjectInstances { - implicit def catsReflexiveInjectInstance[F[_]]: Inject[F, F] = - new Inject[F, F] { - val inj = λ[FunctionK[F, F]](identity(_)) +private[cats] sealed abstract class InjectKInstances { + implicit def catsReflexiveInjectKInstance[F[_]]: InjectK[F, F] = + new InjectK[F, F] { + val inj = FunctionK.id[F] val prj = λ[FunctionK[F, λ[α => Option[F[α]]]]](Some(_)) } - implicit def catsLeftInjectInstance[F[_], G[_]]: Inject[F, EitherK[F, G, ?]] = - new Inject[F, EitherK[F, G, ?]] { + implicit def catsLeftInjectKInstance[F[_], G[_]]: InjectK[F, EitherK[F, G, ?]] = + new InjectK[F, EitherK[F, G, ?]] { val inj = λ[FunctionK[F, EitherK[F, G, ?]]](EitherK.leftc(_)) val prj = λ[FunctionK[EitherK[F, G, ?], λ[α => Option[F[α]]]]](_.run.left.toOption) } - implicit def catsRightInjectInstance[F[_], G[_], H[_]](implicit I: Inject[F, G]): Inject[F, EitherK[H, G, ?]] = - new Inject[F, EitherK[H, G, ?]] { + implicit def catsRightInjectKInstance[F[_], G[_], H[_]](implicit I: InjectK[F, G]): InjectK[F, EitherK[H, G, ?]] = + new InjectK[F, EitherK[H, G, ?]] { val inj = λ[FunctionK[G, EitherK[H, G, ?]]](EitherK.rightc(_)) compose I.inj val prj = λ[FunctionK[EitherK[H, G, ?], λ[α => Option[F[α]]]]](_.run.right.toOption.flatMap(I.prj(_))) } } -object Inject extends InjectInstances { - def apply[F[_], G[_]](implicit I: Inject[F, G]): Inject[F, G] = I +object InjectK extends InjectKInstances { + def apply[F[_], G[_]](implicit I: InjectK[F, G]): InjectK[F, G] = I } diff --git a/core/src/main/scala/cats/Show.scala b/core/src/main/scala/cats/Show.scala index 7e9f01e745d..a266952c398 100644 --- a/core/src/main/scala/cats/Show.scala +++ b/core/src/main/scala/cats/Show.scala @@ -11,7 +11,7 @@ import cats.functor.Contravariant * explicitly provided one. */ @typeclass trait Show[-T] { - def show(f: T): String + def show(t: T): String } object Show { diff --git a/core/src/main/scala/cats/Traverse.scala b/core/src/main/scala/cats/Traverse.scala index 32e83215cbd..24015db6b96 100644 --- a/core/src/main/scala/cats/Traverse.scala +++ b/core/src/main/scala/cats/Traverse.scala @@ -32,24 +32,6 @@ import simulacrum.typeclass */ def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] - /** - * Behaves just like traverse, but uses [[Unapply]] to find the - * Applicative instance for G. - * - * Example: - * {{{ - * scala> import cats.implicits._ - * scala> def parseInt(s: String): Either[String, Int] = Either.catchOnly[NumberFormatException](s.toInt).leftMap(_ => "no number") - * scala> val ns = List("1", "2", "3") - * scala> ns.traverseU(parseInt) - * res0: Either[String, List[Int]] = Right(List(1, 2, 3)) - * scala> ns.traverse[Either[String, ?], Int](parseInt) - * res1: Either[String, List[Int]] = Right(List(1, 2, 3)) - * }}} - */ - def traverseU[A, GB](fa: F[A])(f: A => GB)(implicit U: Unapply[Applicative, GB]): U.M[F[U.A]] = - U.TC.traverse(fa)(a => U.subst(f(a)))(this) - /** * A traverse followed by flattening the inner result. * @@ -101,24 +83,6 @@ import simulacrum.typeclass def flatSequence[G[_], A](fgfa: F[G[F[A]]])(implicit G: Applicative[G], F: FlatMap[F]): G[F[A]] = G.map(sequence(fgfa))(F.flatten) - /** - * Behaves just like sequence, but uses [[Unapply]] to find the - * Applicative instance for G. - * - * Example: - * {{{ - * scala> import cats.data.{Validated, ValidatedNel} - * scala> import cats.implicits._ - * scala> val x: List[ValidatedNel[String, Int]] = List(Validated.valid(1), Validated.invalid("a"), Validated.invalid("b")).map(_.toValidatedNel) - * scala> x.sequenceU - * res0: cats.data.ValidatedNel[String,List[Int]] = Invalid(NonEmptyList(a, b)) - * scala> x.sequence[ValidatedNel[String, ?], Int] - * res1: cats.data.ValidatedNel[String,List[Int]] = Invalid(NonEmptyList(a, b)) - * }}} - */ - def sequenceU[GA](fga: F[GA])(implicit U: Unapply[Applicative, GA]): U.M[F[U.A]] = - traverse(fga)(U.subst)(U.TC) - def compose[G[_]: Traverse]: Traverse[λ[α => F[G[α]]]] = new ComposedTraverse[F, G] { val F = self diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index 65b0132ce0e..6d862eafe2a 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -39,6 +39,20 @@ final case class Const[A, B](getConst: A) { object Const extends ConstInstances { def empty[A, B](implicit A: Monoid[A]): Const[A, B] = Const(A.empty) + + final class OfPartiallyApplied[B] { + def apply[A](a: A): Const[A, B] = Const(a) + } + + /** + * Convenient syntax for creating a Const[A, B] from an `A` + * {{{ + * scala> import cats.data._ + * scala> Const.of[Int]("a") + * res0: Const[String, Int] = Const(a) + * }}} + */ + def of[B]: OfPartiallyApplied[B] = new OfPartiallyApplied } private[data] sealed abstract class ConstInstances extends ConstInstances0 { diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index 1b514886240..e901c6a86f7 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -89,7 +89,7 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) { def map[D](f: B => D)(implicit F: Functor[F]): EitherT[F, A, D] = bimap(identity, f) def semiflatMap[D](f: B => F[D])(implicit F: Monad[F]): EitherT[F, A, D] = - flatMap(b => EitherT.right[F, A, D](f(b))) + flatMap(b => EitherT.right(f(b))) def leftMap[C](f: A => C)(implicit F: Functor[F]): EitherT[F, C, B] = bimap(f, identity) @@ -195,17 +195,13 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) { * | EitherT(List(Either.right(_.toString), Either.left("error"))) * scala> val fa: EitherT[List, String, Int] = * | EitherT(List(Either.right(1), Either.right(2))) - * scala> type ErrorOr[A] = Either[String, A] - * scala> type ListErrorOr[A] = Nested[List, ErrorOr, A] + * scala> type ListErrorOr[A] = Nested[List, Either[String, ?], A] * scala> ff.ap(fa) * res0: EitherT[List,String,String] = EitherT(List(Right(1), Right(2), Left(error))) * scala> EitherT((ff.toNested: ListErrorOr[Int => String]).ap(fa.toNested: ListErrorOr[Int]).value) * res1: EitherT[List,String,String] = EitherT(List(Right(1), Right(2), Left(error), Left(error))) * }}} * - * Note that we need the `ErrorOr` type alias above because otherwise we can't use the - * syntax function `ap` on `Nested[List, Either[A, ?], B]`. This won't be needed after cats has - * decided [[https://github.com/typelevel/cats/issues/1073 how to handle the SI-2712 fix]]. */ def toNested: Nested[F, Either[A, ?], B] = Nested[F, Either[A, ?], B](value) @@ -236,11 +232,78 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) { object EitherT extends EitherTInstances with EitherTFunctions private[data] trait EitherTFunctions { - final def left[F[_], A, B](fa: F[A])(implicit F: Functor[F]): EitherT[F, A, B] = EitherT(F.map(fa)(Either.left)) - final def right[F[_], A, B](fb: F[B])(implicit F: Functor[F]): EitherT[F, A, B] = EitherT(F.map(fb)(Either.right)) + final class LeftPartiallyApplied[B] private[EitherTFunctions] { + def apply[F[_], A](fa: F[A])(implicit F: Functor[F]): EitherT[F, A, B] = EitherT(F.map(fa)(Either.left)) + } + + /** + * Creates a left version of `EitherT[F, A, B]` from a `F[A]` + * {{{ + * scala> import cats.data.EitherT + * scala> import cats.implicits._ + * scala> EitherT.left[Int](Option("err")) + * res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Left(err))) + * }}} + */ + final def left[B]: LeftPartiallyApplied[B] = new LeftPartiallyApplied[B] + + final class LeftTPartiallyApplied[F[_], B] private[EitherTFunctions] { + def apply[A](a: A)(implicit F: Applicative[F]): EitherT[F, A, B] = EitherT(F.pure(Either.left(a))) + } + + /** + * Creates a left version of `EitherT[F, A, B]` from a `A` + * {{{ + * scala> import cats.data.EitherT + * scala> import cats.implicits._ + * scala> EitherT.leftT[Option, Int]("err") + * res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Left(err))) + * }}} + */ + final def leftT[F[_], B]: LeftTPartiallyApplied[F, B] = new LeftTPartiallyApplied[F, B] + + final class RightPartiallyApplied[A] private[EitherTFunctions] { + def apply[F[_], B](fb: F[B])(implicit F: Functor[F]): EitherT[F, A, B] = EitherT(F.map(fb)(Either.right)) + } + + /** + * Creates a right version of `EitherT[F, A, B]` from a `F[B]` + * {{{ + * scala> import cats.data.EitherT + * scala> import cats.implicits._ + * scala> EitherT.right[String](Option(3)) + * res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(3))) + * }}} + */ + final def right[A]: RightPartiallyApplied[A] = new RightPartiallyApplied[A] + + final class PurePartiallyApplied[F[_], A] private[EitherTFunctions] { + def apply[B](b: B)(implicit F: Applicative[F]): EitherT[F, A, B] = right(F.pure(b)) + } + + /** + * Creates a new `EitherT[F, A, B]` from a `B` + * {{{ + * scala> import cats.data.EitherT + * scala> import cats.implicits._ + * scala> EitherT.pure[Option, String](3) + * res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(3))) + * }}} + */ + final def pure[F[_], A]: PurePartiallyApplied[F, A] = new PurePartiallyApplied[F, A] + + /** + * Alias for [[pure]] + * {{{ + * scala> import cats.data.EitherT + * scala> import cats.implicits._ + * scala> EitherT.rightT[Option, String](3) + * res0: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(3))) + * }}} + */ + final def rightT[F[_], A]: PurePartiallyApplied[F, A] = pure - final def pure[F[_], A, B](b: B)(implicit F: Applicative[F]): EitherT[F, A, B] = right(F.pure(b)) /** * Alias for [[right]] @@ -295,6 +358,19 @@ private[data] trait EitherTFunctions { EitherT(F.pure(Either.fromOption(opt, ifNone))) } + /** Transforms an `F[Option]` into an `EitherT`, using the second argument if the `Option` is a `None`. + * {{{ + * scala> import cats.implicits._ + * scala> val o: Option[Int] = None + * scala> EitherT.fromOptionF(List(o), "Answer not known.") + * res0: EitherT[List, String, Int] = EitherT(List(Left(Answer not known.))) + * scala> EitherT.fromOptionF(List(Option(42)), "Answer not known.") + * res1: EitherT[List, String, Int] = EitherT(List(Right(42))) + * }}} + */ + final def fromOptionF[F[_], E, A](fopt: F[Option[A]], ifNone: => E)(implicit F: Functor[F]): EitherT[F, E, A] = + EitherT(F.map(fopt)(opt => Either.fromOption(opt, ifNone))) + /** If the condition is satisfied, return the given `A` in `Right` * lifted into the specified `Applicative`, otherwise, return the * given `E` in `Left` lifted into the specified `Applicative`. diff --git a/core/src/main/scala/cats/data/Func.scala b/core/src/main/scala/cats/data/Func.scala index 0f3535aa065..350e50329a4 100644 --- a/core/src/main/scala/cats/data/Func.scala +++ b/core/src/main/scala/cats/data/Func.scala @@ -28,9 +28,6 @@ object Func extends FuncInstances { def run: A => F[B] = run0 } - /** applicative function using [[Unapply]]. */ - def appFuncU[A, R](f: A => R)(implicit RR: Unapply[Applicative, R]): AppFunc[RR.M, A, RR.A] = - appFunc({ a: A => RR.subst(f(a)) })(RR.TC) } private[data] abstract class FuncInstances extends FuncInstances0 { diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index e010afa6ed0..f6480d23322 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -82,8 +82,8 @@ 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 } + implicit def catsDataMonoidForKleisli[F[_], A, B](implicit FB0: Monoid[F[B]]): Monoid[Kleisli[F, A, B]] = + new KleisliMonoid[F, A, B] { def FB: Monoid[F[B]] = FB0 } implicit def catsDataMonoidKForKleisli[F[_]](implicit M: Monad[F]): MonoidK[λ[α => Kleisli[F, α, α]]] = Category[Kleisli[F, ?, ?]].algebraK @@ -91,8 +91,8 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 { implicit val catsDataMonoidKForKleisliId: MonoidK[λ[α => Kleisli[Id, α, α]]] = catsDataMonoidKForKleisli[Id] - implicit def catsDataArrowForKleisli[F[_]](implicit ev: Monad[F]): Arrow[Kleisli[F, ?, ?]] = - new KleisliArrow[F] { def F: Monad[F] = ev } + implicit def catsDataArrowForKleisli[F[_]](implicit M: Monad[F]): Arrow[Kleisli[F, ?, ?]] = + new KleisliArrow[F] { def F: Monad[F] = M } implicit val catsDataArrowForKleisliId: Arrow[Kleisli[Id, ?, ?]] = catsDataArrowForKleisli[Id] @@ -102,7 +102,7 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 { 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] = + override def contramap[A, B](fa: Kleisli[F, A, C])(f: B => A): Kleisli[F, B, C] = fa.local(f) } @@ -113,114 +113,70 @@ private[data] sealed abstract class KleisliInstances extends KleisliInstances0 { def liftT[M[_], B](ma: M[B])(implicit ev: Trivial): Kleisli[M, A, B] = Kleisli.lift(ma) } - 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 } + implicit def catsDataApplicativeErrorForKleisli[F[_], A, E](implicit AE: ApplicativeError[F, E]): ApplicativeError[Kleisli[F, A, ?], E] = + new KleisliApplicativeError[F, A, E] { def F: ApplicativeError[F, E] = AE } } private[data] sealed abstract class KleisliInstances0 extends KleisliInstances1 { - - implicit def catsDataMonadErrorForKleisli[F[_], A, E]( - implicit me: MonadError[F, E] - ): MonadError[Kleisli[F, A, ?], E] with MonadReader[Kleisli[F, A, ?], A] = { - new KleisliApplicativeError[F, A, E] - with KleisliMonadReader[F, A] - with MonadError[Kleisli[F, A, ?], E] { - override def M: Monad[F] = me - override def AF: ApplicativeError[F, E] = me - } - } + implicit def catsDataMonadErrorForKleisli[F[_], A, E](implicit ME: MonadError[F, E]): MonadError[Kleisli[F, A, ?], E] = + new KleisliMonadError[F, A, E] { def F: MonadError[F, E] = ME } } private[data] sealed abstract class KleisliInstances1 extends KleisliInstances2 { - - implicit def catsDataMonadReaderForKleisli[F[_]: Monad, A](implicit m: Monad[F]): MonadReader[Kleisli[F, A, ?], A] = { - new KleisliMonadReader[F, A] { - override def M: Monad[F] = m - } - } + implicit def catsDataMonadReaderForKleisli[F[_], A](implicit M: Monad[F]): MonadReader[Kleisli[F, A, ?], A] = + new KleisliMonadReader[F, A] { def F: Monad[F] = M } } private[data] sealed abstract class KleisliInstances2 extends KleisliInstances3 { - implicit def catsDataChoiceForKleisli[F[_]](implicit ev: Monad[F]): Choice[Kleisli[F, ?, ?]] = - new Choice[Kleisli[F, ?, ?]] { - def id[A]: Kleisli[F, A, A] = Kleisli(ev.pure) - - def choice[A, B, C](f: Kleisli[F, A, C], g: Kleisli[F, B, C]): Kleisli[F, Either[A, B], C] = - Kleisli(_.fold(f.run, g.run)) - - def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] = - f.compose(g) - } + implicit def catsDataChoiceForKleisli[F[_]](implicit M: Monad[F]): Choice[Kleisli[F, ?, ?]] = + new KleisliChoice[F] { def F: Monad[F] = M } implicit val catsDataChoiceForKleisliId: Choice[Kleisli[Id, ?, ?]] = catsDataChoiceForKleisli[Id] - implicit def catsDataSplitForKleisli[F[_]](implicit ev: FlatMap[F]): Split[Kleisli[F, ?, ?]] = - new KleisliSplit[F] { def F: FlatMap[F] = ev } + implicit def catsDataSplitForKleisli[F[_]](implicit FM: FlatMap[F]): Split[Kleisli[F, ?, ?]] = + new KleisliSplit[F] { def F: FlatMap[F] = FM } - implicit def catsDataStrongForKleisli[F[_]](implicit ev: Functor[F]): Strong[Kleisli[F, ?, ?]] = - new KleisliStrong[F] { def F: Functor[F] = ev } + implicit def catsDataStrongForKleisli[F[_]](implicit F0: Functor[F]): Strong[Kleisli[F, ?, ?]] = + new KleisliStrong[F] { def F: Functor[F] = F0 } - implicit def catsDataFlatMapForKleisli[F[_], A](implicit ev: FlatMap[F]): FlatMap[Kleisli[F, A, ?]] = - new KleisliFlatMap[F, A] { def FM: FlatMap[F] = ev } + implicit def catsDataFlatMapForKleisli[F[_], A](implicit FM: FlatMap[F]): FlatMap[Kleisli[F, A, ?]] = + new KleisliFlatMap[F, A] { def F: FlatMap[F] = FM } - implicit def catsDataSemigroupForKleisli[F[_], A, B](implicit M: Semigroup[F[B]]): Semigroup[Kleisli[F, A, B]] = - new KleisliSemigroup[F, A, B] { def FB: Semigroup[F[B]] = M } + implicit def catsDataSemigroupForKleisli[F[_], A, B](implicit FB0: Semigroup[F[B]]): Semigroup[Kleisli[F, A, B]] = + new KleisliSemigroup[F, A, B] { def FB: Semigroup[F[B]] = FB0 } - implicit def catsDataSemigroupKForKleisli[F[_]](implicit ev: FlatMap[F]): SemigroupK[λ[α => Kleisli[F, α, α]]] = + implicit def catsDataSemigroupKForKleisli[F[_]](implicit FM: FlatMap[F]): SemigroupK[λ[α => Kleisli[F, α, α]]] = Compose[Kleisli[F, ?, ?]].algebraK } private[data] sealed abstract class KleisliInstances3 extends KleisliInstances4 { - implicit def catsDataApplicativeForKleisli[F[_], A](implicit A : Applicative[F]): Applicative[Kleisli[F, A, ?]] = new KleisliApplicative[F, A] { - implicit def F: Applicative[F] = A - } + implicit def catsDataApplicativeForKleisli[F[_], A](implicit A: Applicative[F]): Applicative[Kleisli[F, A, ?]] = + new KleisliApplicative[F, A] { def F: Applicative[F] = A } } private[data] sealed abstract class KleisliInstances4 extends KleisliInstances5 { - implicit def catsDataApplyForKleisli[F[_]: Apply, A]: Apply[Kleisli[F, A, ?]] = new Apply[Kleisli[F, A, ?]] { - def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] = - fa.ap(f) - - override def product[B, C](fb: Kleisli[F, A, B], fc: Kleisli[F, A, C]): Kleisli[F, A, (B, C)] = - Kleisli(a => Apply[F].product(fb.run(a), fc.run(a))) - - def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] = - fa.map(f) - } + implicit def catsDataApplyForKleisli[F[_], A](implicit A: Apply[F]): Apply[Kleisli[F, A, ?]] = + new KleisliApply[F, A] { def F: Apply[F] = A } } private[data] sealed abstract class KleisliInstances5 { - implicit def catsDataFunctorForKleisli[F[_]: Functor, A]: Functor[Kleisli[F, A, ?]] = new Functor[Kleisli[F, A, ?]] { - def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] = - fa.map(f) - } + implicit def catsDataFunctorForKleisli[F[_], A](implicit F0: Functor[F]): Functor[Kleisli[F, A, ?]] = + new KleisliFunctor[F, A] { def F: Functor[F] = F0 } } -private trait KleisliArrow[F[_]] extends Arrow[Kleisli[F, ?, ?]] with KleisliSplit[F] with KleisliStrong[F] { +private trait KleisliArrow[F[_]] extends Arrow[Kleisli[F, ?, ?]] with KleisliSplit[F] with KleisliStrong[F] with KleisliCategory[F] { implicit def F: Monad[F] def lift[A, B](f: A => B): Kleisli[F, A, B] = Kleisli(a => F.pure(f(a))) - - def id[A]: Kleisli[F, A, A] = - Kleisli(a => F.pure(a)) - - override def second[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (C, A), (C, B)] = - super[KleisliStrong].second(fa) - - override def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] = - super[KleisliSplit].split(f, g) } -private trait KleisliSplit[F[_]] extends Split[Kleisli[F, ?, ?]] { +private trait KleisliSplit[F[_]] extends Split[Kleisli[F, ?, ?]] with KleisliCompose[F] { implicit def F: FlatMap[F] - def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] = + override def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] = Kleisli{ case (a, c) => F.flatMap(f.run(a))(b => F.map(g.run(c))(d => (b, d))) } - - def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] = - f.compose(g) } private trait KleisliStrong[F[_]] extends Strong[Kleisli[F, ?, ?]] { @@ -238,10 +194,28 @@ private trait KleisliStrong[F[_]] extends Strong[Kleisli[F, ?, ?]] { def first[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (A, C), (B, C)] = fa.first[C] - def second[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (C, A), (C, B)] = + override def second[A, B, C](fa: Kleisli[F, A, B]): Kleisli[F, (C, A), (C, B)] = fa.second[C] } +private trait KleisliChoice[F[_]] extends Choice[Kleisli[F, ?, ?]] with KleisliCategory[F] { + def choice[A, B, C](f: Kleisli[F, A, C], g: Kleisli[F, B, C]): Kleisli[F, Either[A, B], C] = + Kleisli(_.fold(f.run, g.run)) +} + +private trait KleisliCategory[F[_]] extends Category[Kleisli[F, ?, ?]] with KleisliCompose[F] { + implicit def F: Monad[F] + + def id[A]: Kleisli[F, A, A] = Kleisli.ask[F, A] +} + +private trait KleisliCompose[F[_]] extends Compose[Kleisli[F, ?, ?]] { + implicit def F: FlatMap[F] + + def compose[A, B, C](f: Kleisli[F, B, C], g: Kleisli[F, A, B]): Kleisli[F, A, C] = + f.compose(g) +} + private trait KleisliSemigroup[F[_], A, B] extends Semigroup[Kleisli[F, A, B]] { implicit def FB: Semigroup[F[B]] @@ -255,63 +229,64 @@ private trait KleisliMonoid[F[_], A, B] extends Monoid[Kleisli[F, A, B]] with Kl override def empty: Kleisli[F, A, B] = Kleisli[F, A, B](a => FB.empty) } -private trait KleisliApplicativeError[F[_], A, E] extends KleisliApplicative[F, A] with ApplicativeError[Kleisli[F, A, ?], E] { - type K[T] = Kleisli[F, A, T] +private trait KleisliMonadError[F[_], A, E] extends MonadError[Kleisli[F, A, ?], E] with KleisliApplicativeError[F, A, E] with KleisliMonadReader[F, A] { + def F: MonadError[F, E] +} - implicit def AF: ApplicativeError[F, E] +private trait KleisliApplicativeError[F[_], A, E] extends ApplicativeError[Kleisli[F, A, ?], E] with KleisliApplicative[F, A] { + type K[T] = Kleisli[F, A, T] - implicit def F: Applicative[F] = AF + implicit def F: ApplicativeError[F, E] - 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)) } - } -private trait KleisliMonadReader[F[_], A] extends KleisliFlatMap[F, A] with KleisliApplicative[F, A] with MonadReader[Kleisli[F, A, ?], A] { - - def M: Monad[F] - - override def F: Applicative[F] = M - override def FM: FlatMap[F] = M - - val ask: Kleisli[F, A, A] = Kleisli(M.pure) +private trait KleisliMonadReader[F[_], A] extends MonadReader[Kleisli[F, A, ?], A] with KleisliMonad[F, A] { + implicit def F: Monad[F] - def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = - Kleisli(f.andThen(fa.run)) + val ask: Kleisli[F, A, A] = Kleisli.ask[F, A] - override def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] = - super[KleisliApplicative].ap(f)(fa) + def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = Kleisli.local(f)(fa) } -private trait KleisliFlatMap[F[_], A] extends FlatMap[Kleisli[F, A, ?]] { +private trait KleisliMonad[F[_], A] extends Monad[Kleisli[F, A, ?]] with KleisliFlatMap[F, A] with KleisliApplicative[F, A] { + implicit def F: Monad[F] +} - implicit def FM: FlatMap[F] +private trait KleisliFlatMap[F[_], A] extends FlatMap[Kleisli[F, A, ?]] with KleisliApply[F, A] { + implicit def F: FlatMap[F] def flatMap[B, C](fa: Kleisli[F, A, B])(f: B => Kleisli[F, A, C]): Kleisli[F, A, C] = fa.flatMap(f) - def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] = - fa.map(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) } }) + Kleisli[F, A, C]({ a => F.tailRecM(b) { f(_).run(a) } }) } -private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] { +private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] with KleisliApply[F, A] { implicit def F: Applicative[F] def pure[B](x: B): Kleisli[F, A, B] = Kleisli.pure[F, A, B](x) +} - def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] = - fa.ap(f) +private trait KleisliApply[F[_], A] extends Apply[Kleisli[F, A, ?]] with KleisliFunctor[F, A] { + implicit def F: Apply[F] - override def map[B, C](fb: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] = - fb.map(f) + override def ap[B, C](f: Kleisli[F, A, B => C])(fa: Kleisli[F, A, B]): Kleisli[F, A, C] = + fa.ap(f) override def product[B, C](fb: Kleisli[F, A, B], fc: Kleisli[F, A, C]): Kleisli[F, A, (B, C)] = - Kleisli(a => Applicative[F].product(fb.run(a), fc.run(a))) + Kleisli(a => F.product(fb.run(a), fc.run(a))) +} + +private trait KleisliFunctor[F[_], A] extends Functor[Kleisli[F, A, ?]] { + implicit def F: Functor[F] + + override def map[B, C](fa: Kleisli[F, A, B])(f: B => C): Kleisli[F, A, C] = + fa.map(f) } diff --git a/core/src/main/scala/cats/data/NonEmptyList.scala b/core/src/main/scala/cats/data/NonEmptyList.scala index 4c03eb5a426..a3c3b138175 100644 --- a/core/src/main/scala/cats/data/NonEmptyList.scala +++ b/core/src/main/scala/cats/data/NonEmptyList.scala @@ -17,14 +17,56 @@ final case class NonEmptyList[+A](head: A, tail: List[A]) { /** * Return the head and tail into a single list + * {{{ + * scala> import cats.data.NonEmptyList + * scala> val nel = NonEmptyList.of(1, 2, 3, 4, 5) + * scala> nel.toList + * res0: scala.collection.immutable.List[Int] = List(1, 2, 3, 4, 5) + * }}} */ def toList: List[A] = head :: tail + /** + * Selects the last element + * {{{ + * scala> import cats.data.NonEmptyList + * scala> val nel = NonEmptyList.of(1, 2, 3, 4, 5) + * scala> nel.last + * res0: Int = 5 + * }}} + */ def last: A = tail.lastOption match { case None => head case Some(a) => a } + /** + * Selects all elements except the last + * + * {{{ + * scala> import cats.data.NonEmptyList + * scala> val nel = NonEmptyList.of(1, 2, 3, 4, 5) + * scala> nel.init + * res0: scala.collection.immutable.List[Int] = List(1, 2, 3, 4) + * }}} + */ + def init: List[A] = tail match { + case Nil => List.empty + case t => head :: t.init + } + + /** + * The size of this NonEmptyList + * + * {{{ + * scala> import cats.data.NonEmptyList + * scala> val nel = NonEmptyList.of(1, 2, 3, 4, 5) + * scala> nel.size + * res0: Int = 5 + * }}} + */ + def size: Int = 1 + tail.size + /** * Applies f to all the elements of the structure */ diff --git a/core/src/main/scala/cats/package.scala b/core/src/main/scala/cats/package.scala index 509536c8a67..cf7b9066d60 100644 --- a/core/src/main/scala/cats/package.scala +++ b/core/src/main/scala/cats/package.scala @@ -10,11 +10,11 @@ package object cats { type ⊥ = Nothing type ⊤ = Any - /** [[cats.Inject]][F, G] */ - type :<:[F[_], G[_]] = Inject[F, G] + /** [[cats.InjectK]][F, G] */ + type :<:[F[_], G[_]] = InjectK[F, G] - /** [[cats.Inject]][F, G] */ - type :≺:[F[_], G[_]] = Inject[F, G] + /** [[cats.InjectK]][F, G] */ + type :≺:[F[_], G[_]] = InjectK[F, G] /** * Identity, encoded as `type Id[A] = A`, a convenient alias to make diff --git a/core/src/main/scala/cats/syntax/apply.scala b/core/src/main/scala/cats/syntax/apply.scala index 2671087bf13..17f9685aafc 100644 --- a/core/src/main/scala/cats/syntax/apply.scala +++ b/core/src/main/scala/cats/syntax/apply.scala @@ -1,16 +1,8 @@ package cats package syntax -private[syntax] trait ApplySyntax1 { - implicit final def catsSyntaxUApply[FA](fa: FA)(implicit U: Unapply[Apply, FA]): Apply.Ops[U.M, U.A] = - new Apply.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait ApplySyntax extends ApplySyntax1 { - implicit def catsSyntaxApply[F[_], A](fa: F[A])(implicit F: Apply[F]): Apply.Ops[F, A] = +trait ApplySyntax { + implicit final def catsSyntaxApply[F[_], A](fa: F[A])(implicit F: Apply[F]): Apply.Ops[F, A] = new Apply.Ops[F, A] { val self = fa val typeClassInstance = F diff --git a/core/src/main/scala/cats/syntax/cartesian.scala b/core/src/main/scala/cats/syntax/cartesian.scala index efff7b43968..c5c4b6bb797 100644 --- a/core/src/main/scala/cats/syntax/cartesian.scala +++ b/core/src/main/scala/cats/syntax/cartesian.scala @@ -1,15 +1,7 @@ package cats package syntax -private[syntax] trait CartesianSyntax1 { - implicit final def catsSyntaxUCartesian[FA](fa: FA)(implicit U: Unapply[Cartesian, FA]): CartesianOps[U.M, U.A] = - new CartesianOps[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait CartesianSyntax extends CartesianSyntax1 { +trait CartesianSyntax { implicit final def catsSyntaxCartesian[F[_], A](fa: F[A])(implicit F: Cartesian[F]): CartesianOps[F, A] = new CartesianOps[F, A] { val self = fa diff --git a/core/src/main/scala/cats/syntax/coflatMap.scala b/core/src/main/scala/cats/syntax/coflatMap.scala index e394677da42..37d860ce1c4 100644 --- a/core/src/main/scala/cats/syntax/coflatMap.scala +++ b/core/src/main/scala/cats/syntax/coflatMap.scala @@ -1,11 +1,4 @@ package cats package syntax -private[syntax] trait CoflatMapSyntax1 { - implicit final def catsSyntaxUCoflatMap[FA](fa: FA)(implicit U: Unapply[CoflatMap, FA]): CoflatMap.Ops[U.M, U.A] = new CoflatMap.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait CoflatMapSyntax extends CoflatMap.ToCoflatMapOps with CoflatMapSyntax1 +trait CoflatMapSyntax extends CoflatMap.ToCoflatMapOps diff --git a/core/src/main/scala/cats/syntax/comonad.scala b/core/src/main/scala/cats/syntax/comonad.scala index cbeaf7bb0fe..77d413ebcca 100644 --- a/core/src/main/scala/cats/syntax/comonad.scala +++ b/core/src/main/scala/cats/syntax/comonad.scala @@ -1,12 +1,5 @@ package cats package syntax -private[syntax] trait ComonadSyntax1 { - implicit final def catsSyntaxUComonad[FA](fa: FA)(implicit U: Unapply[Comonad, FA]): Comonad.Ops[U.M, U.A] = - new Comonad.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} +trait ComonadSyntax extends Comonad.ToComonadOps -trait ComonadSyntax extends Comonad.ToComonadOps with ComonadSyntax1 diff --git a/core/src/main/scala/cats/syntax/contravariant.scala b/core/src/main/scala/cats/syntax/contravariant.scala index 7eda421d6be..996d489adf2 100644 --- a/core/src/main/scala/cats/syntax/contravariant.scala +++ b/core/src/main/scala/cats/syntax/contravariant.scala @@ -3,13 +3,5 @@ package syntax import cats.functor.Contravariant -private[syntax] trait ContravariantSyntax1 { - implicit final def catsSyntaxUContravariant[FA](fa: FA)(implicit U: Unapply[Contravariant, FA]): Contravariant.Ops[U.M, U.A] = - new Contravariant.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait ContravariantSyntax extends Contravariant.ToContravariantOps with ContravariantSyntax1 +trait ContravariantSyntax extends Contravariant.ToContravariantOps diff --git a/core/src/main/scala/cats/syntax/flatMap.scala b/core/src/main/scala/cats/syntax/flatMap.scala index 596019e8605..5fcfc8a339f 100644 --- a/core/src/main/scala/cats/syntax/flatMap.scala +++ b/core/src/main/scala/cats/syntax/flatMap.scala @@ -1,15 +1,7 @@ package cats package syntax -private[syntax] trait FlatMapSyntax1 { - implicit final def catsSyntaxUFlatMap[FA](fa: FA)(implicit U: Unapply[FlatMap, FA]): FlatMap.Ops[U.M, U.A] = - new FlatMap.Ops[U.M, U.A]{ - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait FlatMapSyntax extends FlatMap.ToFlatMapOps with FlatMapSyntax1 { +trait FlatMapSyntax extends FlatMap.ToFlatMapOps { implicit final def catsSyntaxFlatten[F[_]: FlatMap, A](ffa: F[F[A]]): FlattenOps[F, A] = new FlattenOps[F, A](ffa) diff --git a/core/src/main/scala/cats/syntax/foldable.scala b/core/src/main/scala/cats/syntax/foldable.scala index 9a765f08f07..87902c3ca3a 100644 --- a/core/src/main/scala/cats/syntax/foldable.scala +++ b/core/src/main/scala/cats/syntax/foldable.scala @@ -1,15 +1,7 @@ package cats package syntax -private[syntax] trait FoldableSyntax1 { - implicit final def catsSyntaxUFoldable[FA](fa: FA)(implicit U: Unapply[Foldable, FA]): Foldable.Ops[U.M, U.A] = - new Foldable.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait FoldableSyntax extends Foldable.ToFoldableOps with FoldableSyntax1 { +trait FoldableSyntax extends Foldable.ToFoldableOps { implicit final def catsSyntaxNestedFoldable[F[_]: Foldable, G[_], A](fga: F[G[A]]): NestedFoldableOps[F, G, A] = new NestedFoldableOps[F, G, A](fga) } diff --git a/core/src/main/scala/cats/syntax/functor.scala b/core/src/main/scala/cats/syntax/functor.scala index 478299c92aa..f8f4fb9fe72 100644 --- a/core/src/main/scala/cats/syntax/functor.scala +++ b/core/src/main/scala/cats/syntax/functor.scala @@ -1,12 +1,5 @@ package cats package syntax -private[syntax] trait FunctorSyntax1 { - implicit final def catsSyntaxUFunctor[FA](fa: FA)(implicit U: Unapply[Functor, FA]): Functor.Ops[U.M, U.A] = - new Functor.Ops[U.M, U.A]{ - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} +trait FunctorSyntax extends Functor.ToFunctorOps -trait FunctorSyntax extends Functor.ToFunctorOps with FunctorSyntax1 diff --git a/core/src/main/scala/cats/syntax/functorFilter.scala b/core/src/main/scala/cats/syntax/functorFilter.scala index dfefedcce9a..a80b6c2618e 100644 --- a/core/src/main/scala/cats/syntax/functorFilter.scala +++ b/core/src/main/scala/cats/syntax/functorFilter.scala @@ -1,12 +1,4 @@ package cats package syntax -private[syntax] trait FunctorFilterSyntax1 { - implicit final def catsSyntaxUFunctorFilter[FA](fa: FA)(implicit U: Unapply[FunctorFilter, FA]): FunctorFilter.Ops[U.M, U.A] = - new FunctorFilter.Ops[U.M, U.A]{ - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait FunctorFilterSyntax extends FunctorFilter.ToFunctorFilterOps with FunctorFilterSyntax1 +trait FunctorFilterSyntax extends FunctorFilter.ToFunctorFilterOps diff --git a/core/src/main/scala/cats/syntax/invariant.scala b/core/src/main/scala/cats/syntax/invariant.scala index 3f425c002c3..7e5270f535c 100644 --- a/core/src/main/scala/cats/syntax/invariant.scala +++ b/core/src/main/scala/cats/syntax/invariant.scala @@ -3,12 +3,4 @@ package syntax import cats.functor.Invariant -private[syntax] trait InvariantSyntax1 { - implicit final def catsSyntaxUInvariant[FA](fa: FA)(implicit U: Unapply[Invariant, FA]): Invariant.Ops[U.M, U.A] = - new Invariant.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait InvariantSyntax extends Invariant.ToInvariantOps with InvariantSyntax1 +trait InvariantSyntax extends Invariant.ToInvariantOps diff --git a/core/src/main/scala/cats/syntax/monadFilter.scala b/core/src/main/scala/cats/syntax/monadFilter.scala index 8413fb64f59..ee9208eaaf2 100644 --- a/core/src/main/scala/cats/syntax/monadFilter.scala +++ b/core/src/main/scala/cats/syntax/monadFilter.scala @@ -1,12 +1,5 @@ package cats package syntax -private[syntax] trait MonadFilterSyntax1 { - implicit final def catsSyntaxUMonadFilter[FA](fa: FA)(implicit U: Unapply[MonadFilter, FA]): MonadFilter.Ops[U.M, U.A] = - new MonadFilter.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} +trait MonadFilterSyntax extends MonadFilter.ToMonadFilterOps -trait MonadFilterSyntax extends MonadFilter.ToMonadFilterOps with MonadFilterSyntax1 diff --git a/core/src/main/scala/cats/syntax/reducible.scala b/core/src/main/scala/cats/syntax/reducible.scala index a513d884154..10f44874107 100644 --- a/core/src/main/scala/cats/syntax/reducible.scala +++ b/core/src/main/scala/cats/syntax/reducible.scala @@ -1,15 +1,7 @@ package cats package syntax -private[syntax] trait ReducibleSyntax1 { - implicit final def catsSyntaxUReducible[FA](fa: FA)(implicit U: Unapply[Reducible, FA]): Reducible.Ops[U.M, U.A] = - new Reducible.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait ReducibleSyntax extends Reducible.ToReducibleOps with ReducibleSyntax1 { +trait ReducibleSyntax extends Reducible.ToReducibleOps { implicit final def catsSyntaxNestedReducible[F[_]: Reducible, G[_], A](fga: F[G[A]]): NestedReducibleOps[F, G, A] = new NestedReducibleOps[F, G, A](fga) } diff --git a/core/src/main/scala/cats/syntax/semigroupk.scala b/core/src/main/scala/cats/syntax/semigroupk.scala index 39f05b546dd..832501764a7 100644 --- a/core/src/main/scala/cats/syntax/semigroupk.scala +++ b/core/src/main/scala/cats/syntax/semigroupk.scala @@ -1,13 +1,4 @@ package cats package syntax -private[syntax] trait SemigroupKSyntax1 { - // TODO: use simulacrum instances eventually - implicit final def catsSyntaxUSemigroup[FA](fa: FA)(implicit U: Unapply[SemigroupK, FA]): SemigroupK.Ops[U.M, U.A] = - new SemigroupK.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait SemigroupKSyntax extends SemigroupK.ToSemigroupKOps with SemigroupKSyntax1 +trait SemigroupKSyntax extends SemigroupK.ToSemigroupKOps diff --git a/core/src/main/scala/cats/syntax/transLift.scala b/core/src/main/scala/cats/syntax/transLift.scala index f85ed47835f..5f3c228c42d 100644 --- a/core/src/main/scala/cats/syntax/transLift.scala +++ b/core/src/main/scala/cats/syntax/transLift.scala @@ -2,8 +2,7 @@ package cats package syntax trait TransLiftSyntax { - implicit final def catsSyntaxTransLift[E](ma: E)(implicit U: Unapply[Trivial.PH1, E]): TransLiftOps[U.M, U.A] = - new TransLiftOps(U.subst(ma)) + implicit final def catsSyntaxTransLift[M0[_], A](ma: M0[A]): TransLiftOps[M0, A] = new TransLiftOps(ma) } final class TransLiftOps[M0[_], A](val ma: M0[A]) extends AnyVal { diff --git a/core/src/main/scala/cats/syntax/traverse.scala b/core/src/main/scala/cats/syntax/traverse.scala index f004d7ba98e..9205507f3b7 100644 --- a/core/src/main/scala/cats/syntax/traverse.scala +++ b/core/src/main/scala/cats/syntax/traverse.scala @@ -1,12 +1,4 @@ package cats package syntax -private[syntax] trait TraverseSyntax1 { - implicit final def catsSyntaxUTraverse[FA](fa: FA)(implicit U: Unapply[Traverse, FA]): Traverse.Ops[U.M, U.A] = - new Traverse.Ops[U.M, U.A]{ - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait TraverseSyntax extends Traverse.ToTraverseOps with TraverseSyntax1 +trait TraverseSyntax extends Traverse.ToTraverseOps diff --git a/core/src/main/scala/cats/syntax/traverseFilter.scala b/core/src/main/scala/cats/syntax/traverseFilter.scala index 6b241092514..794caeddee1 100644 --- a/core/src/main/scala/cats/syntax/traverseFilter.scala +++ b/core/src/main/scala/cats/syntax/traverseFilter.scala @@ -1,12 +1,4 @@ package cats package syntax -trait TraverseFilterSyntax extends TraverseFilter.ToTraverseFilterOps with TraverseFilterSyntax1 - -private[syntax] trait TraverseFilterSyntax1 { - implicit final def catsSyntaxUTraverseFilter[FA](fa: FA)(implicit U: Unapply[TraverseFilter, FA]): TraverseFilter.Ops[U.M, U.A] = - new TraverseFilter.Ops[U.M, U.A]{ - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} +trait TraverseFilterSyntax extends TraverseFilter.ToTraverseFilterOps diff --git a/docs/src/main/resources/microsite/data/menu.yml b/docs/src/main/resources/microsite/data/menu.yml index 53ae9d0ad22..081dfffe2aa 100644 --- a/docs/src/main/resources/microsite/data/menu.yml +++ b/docs/src/main/resources/microsite/data/menu.yml @@ -124,6 +124,10 @@ options: url: datatypes/freemonad.html menu_type: data + - title: FunctionK + url: datatypes/functionk.html + menu_type: data + - title: Id url: datatypes/id.html menu_type: data diff --git a/docs/src/main/tut/datatypes/freemonad.md b/docs/src/main/tut/datatypes/freemonad.md index dc1d0b344f8..9febc17f2fb 100644 --- a/docs/src/main/tut/datatypes/freemonad.md +++ b/docs/src/main/tut/datatypes/freemonad.md @@ -298,7 +298,7 @@ val result: (Map[String, Any], Option[Int]) = program.foldMap(pureCompiler).run( ## Composing Free monads ADTs. Real world applications often time combine different algebras. -The `Inject` type class described by Swierstra in [Data types à la carte](http://www.staff.science.uu.nl/~swier004/publications/2008-jfp.pdf) +The injection type class described by Swierstra in [Data types à la carte](http://www.staff.science.uu.nl/~swier004/publications/2008-jfp.pdf) lets us compose different algebras in the context of `Free`. Let's see a trivial example of unrelated ADT's getting composed as a `EitherK` that can form a more complex program. @@ -306,7 +306,7 @@ Let's see a trivial example of unrelated ADT's getting composed as a `EitherK` t ```tut:silent import cats.data.EitherK import cats.free.Free -import cats.{Id, Inject, ~>} +import cats.{Id, InjectK, ~>} import scala.collection.mutable.ListBuffer ``` @@ -331,22 +331,22 @@ type CatsApp[A] = EitherK[DataOp, Interact, A] In order to take advantage of monadic composition we use smart constructors to lift our Algebra to the `Free` context. ```tut:silent -class Interacts[F[_]](implicit I: Inject[Interact, F]) { +class Interacts[F[_]](implicit I: InjectK[Interact, F]) { def tell(msg: String): Free[F, Unit] = Free.inject[Interact, F](Tell(msg)) def ask(prompt: String): Free[F, String] = Free.inject[Interact, F](Ask(prompt)) } object Interacts { - implicit def interacts[F[_]](implicit I: Inject[Interact, F]): Interacts[F] = new Interacts[F] + implicit def interacts[F[_]](implicit I: InjectK[Interact, F]): Interacts[F] = new Interacts[F] } -class DataSource[F[_]](implicit I: Inject[DataOp, F]) { +class DataSource[F[_]](implicit I: InjectK[DataOp, F]) { def addCat(a: String): Free[F, Unit] = Free.inject[DataOp, F](AddCat(a)) def getAllCats: Free[F, List[String]] = Free.inject[DataOp, F](GetAllCats()) } object DataSource { - implicit def dataSource[F[_]](implicit I: Inject[DataOp, F]): DataSource[F] = new DataSource[F] + implicit def dataSource[F[_]](implicit I: InjectK[DataOp, F]): DataSource[F] = new DataSource[F] } ``` @@ -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. @@ -521,7 +521,7 @@ 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]) { def writeLine(line : String) : TeletypeT[M, Unit] = @@ -543,11 +543,11 @@ def program(implicit TO : TeletypeOps[TeletypeState]) : TeletypeT[TeletypeState, userSaid <- TO.readLine("what's up?!") _ <- 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) diff --git a/docs/src/main/tut/datatypes/functionk.md b/docs/src/main/tut/datatypes/functionk.md new file mode 100644 index 00000000000..f2fe719c8af --- /dev/null +++ b/docs/src/main/tut/datatypes/functionk.md @@ -0,0 +1,123 @@ +--- +layout: docs +title: "FunctionK" +section: "data" +source: "core/src/main/scala/cats/arrow/FunctionK.scala" +scaladoc: "#cats.arrow.FunctionK" +--- +# FunctionK +A `FunctionK` transforms values from one first-order-kinded type (a type that takes a single type +parameter, such as `List` or `Option`) into another first-order-kinded type. This transformation is +universal, meaning that a `FunctionK[List, Option]` will translate all `List[A]` values into an +`Option[A]` value for all possible types of `A`. This explanation may be easier to understand if we +first step back and talk about ordinary functions. + +## Ordinary Functions +Consider the following scala method: + +```tut:silent +def first(l: List[Int]): Option[Int] = l.headOption +``` + +This isn't a particularly helpful method, but it will work as an example. Instead of writing this as a +method, we could have written this as a function _value_: + +```tut:silent +val first: List[Int] => Option[Int] = l => l.headOption +``` + +And here, `=>` is really just some syntactic sugar for `Function1`, so we could also write that as: + +```tut:silent +val first: Function1[List[Int], Option[Int]] = l => l.headOption +```` + +Let's cut through the syntactic sugar even a little bit further. `Function1` isn't really a special type. +It's just a trait that looks something like this: + +```tut:silent +// we are calling this `MyFunction1` so we don't collide with the actual `Function1` +trait MyFunction1[A, B] { + def apply(a: A): B +} +``` + +So if we didn't mind being a bit verbose, we could have written our function as: + +```tut:silent +val first: Function1[List[Int], Option[Int]] = new Function1[List[Int], Option[Int]] { + def apply(l: List[Int]): Option[Int] = l.headOption +} +``` + +## Abstracting via Generics + +Recall our `first` method: + +```tut:silent +def first(l: List[Int]): Option[Int] = l.headOption +``` + +The astute reader may have noticed that there's really no reason that this method needs to be tied directly to `Int`. We could use generics to make this a bit more general: + +``` +def first[A](l: List[A]): Option[A] = l.headOption +``` + +But how would we represent this new `first` method as a `=>`/`Function1` value? We are looking for something like a type of `List[A] => Option[A] forAll A`, but this isn't valid scala syntax. `Function1` isn't quite the right fit, because its `apply` method doesn't take a generic type parameter. + +## Higher Kinds to the Rescue + +It turns out that we can represent our universal `List` to `Option` transformation with something that looks a bit like `Function1` but +that adds a type parameter to the `apply` method and utilizes higher kinds: + +```tut:silent +trait MyFunctionK[F[_], G[_]] { + def apply[A](fa: F[A]): G[A] +} +``` + +Cats provides this type as `FunctionK` (we used `MyFunctionK` for our example type to avoid confusion). So now we can write `first` as a `FunctionK[List, Option]` value: + +```tut:silent +import cats.arrow.FunctionK + +val first: FunctionK[List, Option] = new FunctionK[List, Option] { + def apply[A](l: List[A]): Option[A] = l.headOption +} +``` + +## Syntactic Sugar + +If the example above looks a bit too verbose for you, the [kind-projector](https://github.com/non/kind-projector) +compiler plugin [provides](https://github.com/non/kind-projector#polymorphic-lambda-values) a more concise syntax. +After adding the plugin to your project, you could write the `first` example as: + +```tut:silent +val first: FunctionK[List, Option] = λ[FunctionK[List, Option]](_.headOption) +``` + +Cats also provides a `~>` type alias for `FunctionK`, so an even more concise version would be: + +```tut:silent +import cats.~> + +val first: List ~> Option = λ[List ~> Option](_.headOption) +``` + +Being able to use `~>` as an alias for `FunctionK` parallels being able to use `=>` as an alias for `Function1`. + +## Use-cases + +`FunctionK` tends to show up when there is abstraction over higher-kinds. For example, interpreters for [free monads](freemonad.html) and [free applicatives](freeapplicative.html) are represented as `FunctionK` instances. + +## Types with more than one type parameter + +Earlier it was mentioned that `FunctionK` operates on first-order-kinded types (types that take a single type parameter such as `List` or `Option`). It's still possible to use `FunctionK` with types that would normally take more than one type parameter (such as `Either`) if we fix all of the type parameters except for one. For example: + +```tut:silent +type ErrorOr[A] = Either[String, A] + +val errorOrFirst: FunctionK[List, ErrorOr] = + λ[FunctionK[List, ErrorOr]](_.headOption.toRight("ERROR: the list was empty!")) +``` diff --git a/docs/src/main/tut/faq.md b/docs/src/main/tut/faq.md index 11bbb7dd437..3cc2626efea 100644 --- a/docs/src/main/tut/faq.md +++ b/docs/src/main/tut/faq.md @@ -11,7 +11,9 @@ position: 4 * [What imports do I need?](#what-imports) * [Where is right-biased `Either`?](#either) + * [Why is the compiler having trouble with types with more than one type parameter?](#si-2712) * [Why can't the compiler find implicit instances for Future?](#future-instances) + * [Why is some example code not compiling for me?](#example-compile) * [How can I turn my List of `` into a `` of a list?](#traverse) * [Where is `ListT`?](#listt) * [Where is `IO`/`Task`?](#task) @@ -47,13 +49,22 @@ There are a few minor mismatches between `Xor` and `Either`. For example, in som Similarly, `cats.data.XorT` has been replaced with `cats.data.EitherT`, although since this is a type defined in Cats, you don't need to import syntax or instances for it (although you may need imports for the underlying monad). +## Why is the compiler having trouble with types with more than one type parameter? + +When you encounter a situation where the same code works fine with a type with one type parameter, e.g. List[A], but doesn't work with types with more than one, e.g. Either[A, B], you probably hit [SI-2712](https://issues.scala-lang.org/browse/SI-2712). Without going into the details, it's highly recommended to enable a partial SI-2712 fix in your project. The easiest way to achieve that is through this [sbt plugin](https://github.com/fiadliel/sbt-partial-unification). +Cats used to provide mitigation to this issue semi-transparently, but given the fact that the fix is now mainstream, we decided to drop that mitigation machinery in favor of reducing the complexity. See this [issue](https://github.com/typelevel/cats/issues/1073) for details. + +## Why is some example code not compiling for me? + +A portion of example code requires either the [Kind-projector](https://github.com/non/kind-projector) compiler plugin or partial unification turned on in scalac. The easiest way to turn partial unification on is through this [sbt plugin](https://github.com/fiadliel/sbt-partial-unification). + ## Why can't the compiler find implicit instances for Future? If you have already followed the [imports advice](#what-imports) but are still getting error messages like `could not find implicit value for parameter e: cats.Monad[scala.concurrent.Future]` or `value |+| is not a member of scala.concurrent.Future[Int]`, then make sure that you have an implicit `scala.concurrent.ExecutionContext` in scope. The easiest way to do this is to `import scala.concurrent.ExecutionContext.Implicits.global`, but note that you may want to use a different execution context for your production application. ## How can I turn my List of `` into a `` of a list? -It's really common to have a `List` of values with types like `Option`, `Either`, or `Validated` that you would like to turn "inside out" into an `Option` (or `Either` or `Validated`) of a `List`. The `sequence`, `sequenceU`, `traverse`, and `traverseU` methods are _really_ handy for this. You can read more about them in the [Traverse documentation]({{ site.baseurl }}/typeclasses/traverse.html). +It's really common to have a `List` of values with types like `Option`, `Either`, or `Validated` that you would like to turn "inside out" into an `Option` (or `Either` or `Validated`) of a `List`. The `sequence` and `traverse` methods are _really_ handy for this. You can read more about them in the [Traverse documentation]({{ site.baseurl }}/typeclasses/traverse.html). ## Where is ListT? diff --git a/docs/src/main/tut/typeclasses/functor.md b/docs/src/main/tut/typeclasses/functor.md index 527a28c8436..11b2459785e 100644 --- a/docs/src/main/tut/typeclasses/functor.md +++ b/docs/src/main/tut/typeclasses/functor.md @@ -106,7 +106,8 @@ nested.map(_ + 1) ``` The `Nested` approach, being a distinct type from its constituents, will resolve the usual way modulo -possible [SI-2712][si2712] issues, but requires syntactic and runtime overhead from wrapping and -unwrapping. +possible [SI-2712][si2712] issues (which can be addressed through [partial unification][partial-unification]), +but requires syntactic and runtime overhead from wrapping and unwrapping. +[partial-unification]: https://github.com/fiadliel/sbt-partial-unification "A sbt plugin for enabling partial unification" [si2712]: https://issues.scala-lang.org/browse/SI-2712 "SI-2712: implement higher-order unification for type constructor inference" diff --git a/docs/src/main/tut/typeclasses/symbols.md b/docs/src/main/tut/typeclasses/symbols.md index dc84bf57925..bb8a796b6d0 100644 --- a/docs/src/main/tut/typeclasses/symbols.md +++ b/docs/src/main/tut/typeclasses/symbols.md @@ -1,6 +1,6 @@ #Symbols -Below is a list of symbols used in cats. +Below is a list of symbols used in cats. The `~>`, `⊥` and `⊤` symbols can be imported with `import cats._`. @@ -25,7 +25,7 @@ A scaladoc generated list is also available on the [Scaladoc symbols page](http: | `x |+| y` | Semigroup combine | [`Semigroup[A]`]({{ site.sources }}/kernel/src/main/scala/cats/kernel/Semigroup.scala) | `combine(x: A, y: A): A` | | `x <+> y` | SemigroupK combine | [`SemigroupK[F[_]]`]({{ site.sources }}/core/src/main/scala/cats/SemigroupK.scala) | `combineK(x: F[A], y: F[A]): F[A]` | | `F ~> G` | natural transformation | [`FunctionK[F[_], G[_]]`]({{ site.sources }}/core/src/main/scala/cats/arrow/FunctionK.scala)| `FunctionK` alias | -| `F :<: G` | inject | [`Inject[F[_], G[_]]`]({{ site.sources }}/free/src/main/scala/cats/free/package.scala) | `Inject` alias | -| `F :≺: G` | inject | [`Inject[F[_], G[_]]`]({{ site.sources }}/free/src/main/scala/cats/free/package.scala) | `Inject` alias | +| `F :<: G` | inject | [`InjectK[F[_], G[_]]`]({{ site.sources }}/free/src/main/scala/cats/free/package.scala) | `InjectK` alias | +| `F :≺: G` | inject | [`InjectK[F[_], G[_]]`]({{ site.sources }}/free/src/main/scala/cats/free/package.scala) | `InjectK` alias | | `⊥` | bottom | [N/A]({{ site.sources }}/core/src/main/scala/cats/package.scala) | `Nothing` | | `⊤` | top | [N/A]({{ site.sources }}/core/src/main/scala/cats/package.scala) | `Any` | diff --git a/free/src/main/scala/cats/free/Free.scala b/free/src/main/scala/cats/free/Free.scala index 3459bb5e41c..aca700bd4c0 100644 --- a/free/src/main/scala/cats/free/Free.scala +++ b/free/src/main/scala/cats/free/Free.scala @@ -140,7 +140,7 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { }(Free.catsFreeMonadForFree) /** - * Lift into `G` (typically a `EitherK`) given `Inject`. Analogous + * Lift into `G` (typically a `EitherK`) given `InjectK`. Analogous * to `Free.inject` but lifts programs rather than constructors. * *{{{ @@ -154,7 +154,7 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { *res4: cats.free.Free[Lo,String] = Free(...) *}}} */ - final def inject[G[_]](implicit ev: Inject[S, G]): Free[G, A] = + final def inject[G[_]](implicit ev: InjectK[S, G]): Free[G, A] = compile(λ[S ~> G](ev.inj(_))) override def toString: String = @@ -209,28 +209,28 @@ object Free { λ[FunctionK[Free[F, ?], M]](f => f.foldMap(fk)) /** - * This method is used to defer the application of an Inject[F, G] + * This method is used to defer the application of an InjectK[F, G] * instance. The actual work happens in - * `FreeInjectPartiallyApplied#apply`. + * `FreeInjectKPartiallyApplied#apply`. * * This method exists to allow the `F` and `G` parameters to be * bound independently of the `A` parameter below. */ - def inject[F[_], G[_]]: FreeInjectPartiallyApplied[F, G] = - new FreeInjectPartiallyApplied + def inject[F[_], G[_]]: FreeInjectKPartiallyApplied[F, G] = + new FreeInjectKPartiallyApplied /** * Pre-application of an injection to a `F[A]` value. */ - final class FreeInjectPartiallyApplied[F[_], G[_]] private[free] { - def apply[A](fa: F[A])(implicit I: Inject[F, G]): Free[G, A] = + final class FreeInjectKPartiallyApplied[F[_], G[_]] private[free] { + def apply[A](fa: F[A])(implicit I: InjectK[F, G]): Free[G, A] = Free.liftF(I.inj(fa)) } - def injectRoll[F[_], G[_], A](ga: G[Free[F, A]])(implicit I: Inject[G, F]): Free[F, A] = + def injectRoll[F[_], G[_], A](ga: G[Free[F, A]])(implicit I: InjectK[G, F]): Free[F, A] = Free.roll(I.inj(ga)) - def match_[F[_], G[_], A](fa: Free[F, A])(implicit F: Functor[F], I: Inject[G, F]): Option[G[Free[F, A]]] = + def match_[F[_], G[_], A](fa: Free[F, A])(implicit F: Functor[F], I: InjectK[G, F]): Option[G[Free[F, A]]] = fa.resume.fold(I.prj(_), _ => None) /** diff --git a/free/src/main/scala/cats/free/FreeT.scala b/free/src/main/scala/cats/free/FreeT.scala index 9ee24ba702e..99c589f9b82 100644 --- a/free/src/main/scala/cats/free/FreeT.scala +++ b/free/src/main/scala/cats/free/FreeT.scala @@ -164,10 +164,6 @@ object FreeT extends FreeTInstances { def liftT[S[_], M[_], A](value: M[A])(implicit M: Functor[M]): FreeT[S, M, A] = Suspend(M.map(value)(Right(_))) - /** A version of `liftT` that infers the nested type constructor. */ - def liftTU[S[_], MA](value: MA)(implicit M: Unapply[Functor, MA]): FreeT[S, M.M, M.A] = - liftT[S, M.M, M.A](M.subst(value))(M.TC) - /** Suspends a value within a functor in a single step. Monadic unit for a higher-order monad. */ def liftF[S[_], M[_], A](value: S[A])(implicit M: Applicative[M]): FreeT[S, M, A] = Suspend(M.pure(Left(value))) diff --git a/free/src/test/scala/cats/free/FreeTTests.scala b/free/src/test/scala/cats/free/FreeTTests.scala index 4705fbdbe95..8efdeb83c8e 100644 --- a/free/src/test/scala/cats/free/FreeTTests.scala +++ b/free/src/test/scala/cats/free/FreeTTests.scala @@ -141,9 +141,9 @@ class FreeTTests extends CatsSuite { result.toString.length should be > 0 } - private[free] def liftTUCompilationTests() = { + private[free] def liftTCompilationTests() = { val a: Either[String, Int]= Right(42) - val b: FreeT[Option, Either[String, ?], Int] = FreeT.liftTU(a) + val b: FreeT[Option, Either[String, ?], Int] = FreeT.liftT(a) } } @@ -153,7 +153,6 @@ object FreeTTests extends FreeTTestsInstances { import Arbitrary._ import org.scalacheck.Arbitrary - implicit def freeTIntStateArb[A: Arbitrary]: Arbitrary[FreeTState[A]] = freeTArb[IntState, IntState, A] implicit def freeTArb[F[_], G[_]: Applicative, A](implicit F: Arbitrary[F[A]], G: Arbitrary[G[A]], A: Arbitrary[A]): Arbitrary[FreeT[F, G, A]] = Arbitrary(freeTGen[F, G, A](4)) diff --git a/project/plugins.sbt b/project/plugins.sbt index 265c059fc61..35d86e72885 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -12,3 +12,4 @@ addSbtPlugin("com.github.tkawachi" % "sbt-doctest" % "0.4.1") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1") addSbtPlugin("com.fortysevendeg" % "sbt-microsites" % "0.3.2") addSbtPlugin("com.dwijnand" % "sbt-travisci" % "1.0.0-M4") +addSbtPlugin("org.lyranthe.sbt" % "partial-unification" % "1.0.0") diff --git a/tests/src/test/scala/cats/tests/EitherTTests.scala b/tests/src/test/scala/cats/tests/EitherTTests.scala index dbe79220ce7..e97648853e0 100644 --- a/tests/src/test/scala/cats/tests/EitherTTests.scala +++ b/tests/src/test/scala/cats/tests/EitherTTests.scala @@ -193,33 +193,33 @@ class EitherTTests extends CatsSuite { } test("recover recovers handled values") { - val eithert = EitherT.left[Id, String, Int]("eithert") + val eithert = EitherT.leftT[Id, Int]("eithert") eithert.recover { case "eithert" => 5 }.isRight should === (true) } test("recover ignores unhandled values") { - val eithert = EitherT.left[Id, String, Int]("eithert") + val eithert = EitherT.leftT[Id, Int]("eithert") eithert.recover { case "noteithert" => 5 } should === (eithert) } test("recover ignores the right side") { - val eithert = EitherT.right[Id, String, Int](10) + val eithert = EitherT.pure[Id, String](10) eithert.recover { case "eithert" => 5 } should === (eithert) } test("recoverWith recovers handled values") { - val eithert = EitherT.left[Id, String, Int]("eithert") - eithert.recoverWith { case "eithert" => EitherT.right[Id, String, Int](5) }.isRight should === (true) + val eithert = EitherT.leftT[Id, Int]("eithert") + eithert.recoverWith { case "eithert" => EitherT.pure[Id, String](5) }.isRight should === (true) } test("recoverWith ignores unhandled values") { - val eithert = EitherT.left[Id, String, Int]("eithert") - eithert.recoverWith { case "noteithert" => EitherT.right[Id, String, Int](5) } should === (eithert) + val eithert = EitherT.leftT[Id, Int]("eithert") + eithert.recoverWith { case "noteithert" => EitherT.pure[Id, String](5) } should === (eithert) } test("recoverWith ignores the right side") { - val eithert = EitherT.right[Id, String, Int](10) - eithert.recoverWith { case "eithert" => EitherT.right[Id, String, Int](5) } should === (eithert) + val eithert = EitherT.pure[Id, String](10) + eithert.recoverWith { case "eithert" => EitherT.pure[Id, String](5) } should === (eithert) } test("transform consistent with value.map") { @@ -374,7 +374,7 @@ class EitherTTests extends CatsSuite { test("ensure should fail if predicate not satisfied") { forAll { (x: EitherT[Id, String, Int], s: String, p: Int => Boolean) => if (x.isRight && !p(x getOrElse 0)) { - x.ensure(s)(p) should === (EitherT.left[Id, String, Int](s)) + x.ensure(s)(p) should === (EitherT.leftT[Id, Int](s)) } } } diff --git a/tests/src/test/scala/cats/tests/InjectTests.scala b/tests/src/test/scala/cats/tests/InjectKTests.scala similarity index 79% rename from tests/src/test/scala/cats/tests/InjectTests.scala rename to tests/src/test/scala/cats/tests/InjectKTests.scala index 692d08d99dc..612bc26b756 100644 --- a/tests/src/test/scala/cats/tests/InjectTests.scala +++ b/tests/src/test/scala/cats/tests/InjectKTests.scala @@ -4,7 +4,7 @@ import cats.data.EitherK import cats.tests.CatsSuite import org.scalacheck._ -class InjectTests extends CatsSuite { +class InjectKTests extends CatsSuite { sealed trait Test1Algebra[A] @@ -52,8 +52,8 @@ class InjectTests extends CatsSuite { } yield x + y forAll { (x: Int, y: Int) => - val expr1: T[Int] = Inject[Test1Algebra, T].inj(Test1(x, _ + 1)) - val expr2: T[Int] = Inject[Test2Algebra, T].inj(Test2(y, _ * 2)) + val expr1: T[Int] = InjectK[Test1Algebra, T].inj(Test1(x, _ + 1)) + val expr2: T[Int] = InjectK[Test2Algebra, T].inj(Test2(y, _ * 2)) val res = distr[T, Int](expr1, expr2) res should ===(Some(x + y)) } @@ -71,8 +71,8 @@ class InjectTests extends CatsSuite { } yield x + y forAll { (x: Int, y: Int) => - val expr1: T[Int] = Inject[Test1Algebra, T].apply(Test1(x, _ + 1)) - val expr2: T[Int] = Inject[Test2Algebra, T].apply(Test2(y, _ * 2)) + val expr1: T[Int] = InjectK[Test1Algebra, T].apply(Test1(x, _ + 1)) + val expr2: T[Int] = InjectK[Test2Algebra, T].apply(Test2(y, _ * 2)) val res = distr[T, Int](expr1, expr2) res should ===(Some(x + y)) } @@ -80,20 +80,20 @@ class InjectTests extends CatsSuite { test("apply in left") { forAll { (y: Test1Algebra[Int]) => - Inject[Test1Algebra, T].inj(y) == EitherK(Left(y)) should ===(true) + InjectK[Test1Algebra, T].inj(y) == EitherK(Left(y)) should ===(true) } } test("apply in right") { forAll { (y: Test2Algebra[Int]) => - Inject[Test2Algebra, T].inj(y) == EitherK(Right(y)) should ===(true) + InjectK[Test2Algebra, T].inj(y) == EitherK(Right(y)) should ===(true) } } test("null identity") { val listIntNull = null.asInstanceOf[List[Int]] - Inject.catsReflexiveInjectInstance[List].inj[Int](listIntNull) should ===(listIntNull) - Inject.catsReflexiveInjectInstance[List].prj[Int](listIntNull) should ===(Some(listIntNull)) + InjectK.catsReflexiveInjectKInstance[List].inj[Int](listIntNull) should ===(listIntNull) + InjectK.catsReflexiveInjectKInstance[List].prj[Int](listIntNull) should ===(Some(listIntNull)) } } diff --git a/tests/src/test/scala/cats/tests/KleisliTests.scala b/tests/src/test/scala/cats/tests/KleisliTests.scala index 9fedfb3bf00..4fb32452df2 100644 --- a/tests/src/test/scala/cats/tests/KleisliTests.scala +++ b/tests/src/test/scala/cats/tests/KleisliTests.scala @@ -19,8 +19,10 @@ class KleisliTests extends CatsSuite { kleisliEq implicit val eitherTEq = EitherT.catsDataEqForEitherT[Kleisli[Option, Int, ?], Unit, Int] + implicit val eitherTEq2 = EitherT.catsDataEqForEitherT[Reader[Int, ?], Unit, Int] implicit val iso = CartesianTests.Isomorphisms.invariant[Kleisli[Option, Int, ?]] + implicit val iso2 = CartesianTests.Isomorphisms.invariant[Reader[Int, ?]] checkAll("Kleisli[Option, Int, Int] with Unit", ApplicativeErrorTests[Kleisli[Option, Int, ?], Unit].applicativeError[Int, Int, Int]) checkAll("ApplicativeError[Kleisli[Option, Int, Int], Unit]", SerializableTests.serializable(ApplicativeError[Kleisli[Option, Int, ?], Unit])) @@ -49,6 +51,12 @@ class KleisliTests extends CatsSuite { checkAll("MonadReader[Kleisli[Option, ?, ?], Int]", SerializableTests.serializable(MonadReader[Kleisli[Option, Int, ?], Int])) } + { + implicit val catsDataMonadReaderForReader = Kleisli.catsDataMonadReaderForKleisliId[Int] + checkAll("Reader[Int, Int]", MonadReaderTests[Reader[Int, ?], Int].monadReader[Int, Int, Int]) + checkAll("MonadReader[Reader[?, ?], Int]", SerializableTests.serializable(MonadReader[Reader[Int, ?], Int])) + } + { implicit val kleisliSplit = Kleisli.catsDataSplitForKleisli[Option] checkAll("Kleisli[Option, Int, Int]", SplitTests[Kleisli[Option, ?, ?]].split[Int, Int, Int, Int, Int, Int]) @@ -215,10 +223,7 @@ class KleisliTests extends CatsSuite { FlatMap[IntReader] Semigroup[IntReader[String]] - // ApplicativeError and MonadError (some SI-2712 workarounds are needed) - type UnitValidated[A] = cats.data.Validated[Unit, A] - type KleisliUV[A] = Kleisli[UnitValidated, Int, A] - ApplicativeError[KleisliUV, Unit] + ApplicativeError[Kleisli[cats.data.Validated[Unit, ?], Int, ?], Unit] ApplicativeError[Kleisli[Option, Int, ?], Unit] MonadError[Kleisli[Option, Int, ?], Unit] } diff --git a/tests/src/test/scala/cats/tests/MonadTest.scala b/tests/src/test/scala/cats/tests/MonadTest.scala index 0df78f6688e..8b8935a4973 100644 --- a/tests/src/test/scala/cats/tests/MonadTest.scala +++ b/tests/src/test/scala/cats/tests/MonadTest.scala @@ -8,10 +8,8 @@ class MonadTest extends CatsSuite { implicit val testInstance: MonadState[StateT[Id, Int, ?], Int] = StateT.catsDataMonadStateForStateT[Id, Int] import testInstance._ - type StateIdInt[T] = StateT[Id, Int, T] //workaround for SI-2712 - - val increment: StateIdInt[Unit] = modify(_ + 1) - val incrementAndGet: StateIdInt[Int] = increment >> get + val increment: StateT[Id, Int, Unit] = modify(_ + 1) + val incrementAndGet: StateT[Id, Int, Int] = increment >> get test("whileM_") { forAll(Gen.posNum[Int]) { (max: Int) => diff --git a/tests/src/test/scala/cats/tests/NestedTests.scala b/tests/src/test/scala/cats/tests/NestedTests.scala index fc108bffe11..6f70f69fdb5 100644 --- a/tests/src/test/scala/cats/tests/NestedTests.scala +++ b/tests/src/test/scala/cats/tests/NestedTests.scala @@ -1,6 +1,7 @@ package cats package tests +import cats.Functor import cats.data._ import cats.functor._ import cats.laws.discipline._ @@ -15,11 +16,6 @@ class NestedTests extends CatsSuite { implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 20, sizeRange = 5) - implicit val iso = { - implicit val instance = ListWrapper.functor - invariant[Nested[List, ListWrapper, ?]] - } - { // Invariant composition implicit val instance = ListWrapper.invariant @@ -76,12 +72,8 @@ class NestedTests extends CatsSuite { { // Contravariant + Contravariant = Functor type ConstInt[A] = Const[Int, A] - // SI-2712 - implicit val instance = Nested.catsDataContravariantForNested[ConstInt, Show] - implicit val arbitrary = catsLawsArbitraryForNested[ConstInt, Show, Int] - implicit val eqv = Nested.catsDataEqForNested[ConstInt, Show, Int] checkAll("Nested[Const[Int, ?], Show, ?]", FunctorTests[Nested[ConstInt, Show, ?]].functor[Int, Int, Int]) - checkAll("Functor[Nested[Const[Int, ?], Show, ?]]", SerializableTests.serializable(instance)) + checkAll("Functor[Nested[Const[Int, ?], Show, ?]]", SerializableTests.serializable(Functor[Nested[ConstInt, Show, ?]])) } { diff --git a/tests/src/test/scala/cats/tests/NonEmptyListTests.scala b/tests/src/test/scala/cats/tests/NonEmptyListTests.scala index a1d501314e6..7773f9d354f 100644 --- a/tests/src/test/scala/cats/tests/NonEmptyListTests.scala +++ b/tests/src/test/scala/cats/tests/NonEmptyListTests.scala @@ -238,6 +238,18 @@ class NonEmptyListTests extends CatsSuite { } } + test("NonEmptyList#init is consistent with List#init") { + forAll { nel: NonEmptyList[Int] => + nel.init should === (nel.toList.init) + } + } + + test("NonEmptyList#size is consistent with List#size") { + forAll { nel: NonEmptyList[Int] => + nel.size should === (nel.toList.size) + } + } + test("NonEmptyList#sorted is consistent with List#sorted") { forAll { nel: NonEmptyList[Int] => nel.sorted.toList should === (nel.toList.sorted) diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index 041d72d0e00..16d26315aad 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -1,7 +1,7 @@ package cats package tests -import cats.data.{EitherT, OptionT} +import cats.data.OptionT import cats.kernel.laws.{GroupLaws, OrderLaws} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ @@ -72,19 +72,6 @@ class OptionTTests extends CatsSuite { implicit val monadError = OptionT.catsDataMonadErrorForOptionT[SEither, String] - import org.scalacheck.Arbitrary - implicit val arb1 = implicitly[Arbitrary[OptionT[SEither, Int]]] - implicit val arb2 = implicitly[Arbitrary[OptionT[SEither, Int => Int]]] - - implicit val eq0 = OptionT.catsDataEqForOptionT[SEither, Option[Int]] - implicit val eq1 = OptionT.catsDataEqForOptionT[SEither, Int] - implicit val eq2 = OptionT.catsDataEqForOptionT[SEither, Unit] - implicit val eq3 = OptionT.catsDataEqForOptionT[SEither, SEither[Unit]] - implicit val eq4 = OptionT.catsDataEqForOptionT[SEither, SEither[Int]] - implicit val eq5 = EitherT.catsDataEqForEitherT[OptionT[SEither, ?], String, Int] - implicit val eq6 = OptionT.catsDataEqForOptionT[SEither, (Int, Int, Int)] - - implicit val iso = CartesianTests.Isomorphisms.invariant[OptionT[SEither, ?]] checkAll("OptionT[Either[String, ?], Int]", MonadErrorTests[OptionT[SEither, ?], String].monadError[Int, Int, Int]) checkAll("MonadError[OptionT[Either[String, ?], ?]]", SerializableTests.serializable(monadError)) diff --git a/tests/src/test/scala/cats/tests/RegressionTests.scala b/tests/src/test/scala/cats/tests/RegressionTests.scala index 50f000c87a7..cacd06504ec 100644 --- a/tests/src/test/scala/cats/tests/RegressionTests.scala +++ b/tests/src/test/scala/cats/tests/RegressionTests.scala @@ -85,7 +85,7 @@ class RegressionTests extends CatsSuite { test("#500: foldMap - traverse consistency") { assert( - List(1,2,3).traverseU(i => Const(List(i))).getConst == List(1,2,3).foldMap(List(_)) + List(1,2,3).traverse(i => Const.of[List[Int]](List(i))).getConst == List(1,2,3).foldMap(List(_)) ) } @@ -101,31 +101,31 @@ class RegressionTests extends CatsSuite { count = 0 } - List(1,2,6,8).traverseU(validate) should === (Either.left("6 is greater than 5")) + List(1,2,6,8).traverse(validate) should === (Either.left("6 is greater than 5")) // shouldn't have ever evaluted validate(8) checkAndResetCount(3) - Stream(1,2,6,8).traverseU(validate) should === (Either.left("6 is greater than 5")) + Stream(1,2,6,8).traverse(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(3) type StringMap[A] = Map[String, A] val intMap: StringMap[Int] = Map("one" -> 1, "two" -> 2, "six" -> 6, "eight" -> 8) - intMap.traverseU(validate) should === (Either.left("6 is greater than 5")) + intMap.traverse(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(3) - NonEmptyList.of(1,2,6,8).traverseU(validate) should === (Either.left("6 is greater than 5")) + NonEmptyList.of(1,2,6,8).traverse(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(3) - NonEmptyList.of(6,8).traverseU(validate) should === (Either.left("6 is greater than 5")) + NonEmptyList.of(6,8).traverse(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(1) - List(1,2,6,8).traverseU_(validate) should === (Either.left("6 is greater than 5")) + List(1,2,6,8).traverse_(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(3) - NonEmptyList.of(1,2,6,7,8).traverseU_(validate) should === (Either.left("6 is greater than 5")) + NonEmptyList.of(1,2,6,7,8).traverse_(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(3) - NonEmptyList.of(6,7,8).traverseU_(validate) should === (Either.left("6 is greater than 5")) + NonEmptyList.of(6,7,8).traverse_(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(1) } } diff --git a/tests/src/test/scala/cats/tests/StateTTests.scala b/tests/src/test/scala/cats/tests/StateTTests.scala index 9d78e1bd587..3fcf1edad8a 100644 --- a/tests/src/test/scala/cats/tests/StateTTests.scala +++ b/tests/src/test/scala/cats/tests/StateTTests.scala @@ -17,7 +17,7 @@ class StateTTests extends CatsSuite { test("traversing state is stack-safe"){ val ns = (0 to 100000).toList - val x = ns.traverseU(_ => add1) + val x = ns.traverse(_ => add1) x.runS(0).value should === (100001) } diff --git a/tests/src/test/scala/cats/tests/UnapplyTests.scala b/tests/src/test/scala/cats/tests/UnapplyTests.scala index 623dbd33814..9044fbfdc49 100644 --- a/tests/src/test/scala/cats/tests/UnapplyTests.scala +++ b/tests/src/test/scala/cats/tests/UnapplyTests.scala @@ -8,24 +8,26 @@ import cats.laws.discipline.SerializableTests // important is that this stuff compiles at all. class UnapplyTests extends CatsSuite { - test("Unapply works for stuff already the right kind") { - val x = Traverse[List].traverseU(List(1,2,3))(Option(_)) - x should === (Some(List(1,2,3))) + + test("Unapply works for F[_] ") { + + val u = implicitly[Unapply.Aux1[Functor, Option[Int], Option, Int]] + + u.TC.map(u.subst(Option(1)))(_ + 1) should ===(Option(2)) } - test("Unapply works for F[_,_] with the left fixed") { - val x = Traverse[List].traverseU(List(1,2,3))(Either.right(_)) - (x: Either[String, List[Int]]) should === (Either.right(List(1,2,3))) + test("Unapply works for F[_, _] with left fixed ") { + + val u = implicitly[Unapply.Aux1[Functor, Either[String, Int], Either[String, ?], Int]] + + u.TC.map(u.subst(1.asRight[String]))(_ + 1) should ===(2.asRight[String]) } test("Unapply works for F[_[_],_] with the left fixed") { - val x: OptionT[List, Int] = OptionT(List(Option(1), Option(2))) - val y: OptionT[List, Int] = OptionT(List(Option(3), Option(4))) - val z: List[Option[(Int,Int)]] = (x |@| y).tupled.value + val u = implicitly[Unapply.Aux1[Functor, OptionT[List, Int], OptionT[List, ?], Int]] - z should be (List(Option((1,3)), Option((1,4)), - Option((2,3)), Option((2,4)))) + u.TC.map(u.subst(OptionT(List(Option(1)))))(_ + 1) should ===(OptionT(List(Option(2)))) } checkAll("Unapply[Functor, Option[String]]", SerializableTests.serializable(Unapply[Functor, Option[String]])) @@ -34,6 +36,8 @@ class UnapplyTests extends CatsSuite { val x: List[Option[Int]] = List(Option(1), Option(2)) val y: Nested[List, Option, Int] = Nested(x) - y.map(_ + 1).value should === (x.map(_.map(_ + 1))) + val u = implicitly[Unapply.Aux1[Functor, Nested[List, Option, Int], Nested[List, Option, ?], Int]] + + u.TC.map(u.subst(y))(_ + 1).value should ===(x.map(_.map(_ + 1))) } } diff --git a/tests/src/test/scala/cats/tests/WordCountTest.scala b/tests/src/test/scala/cats/tests/WordCountTest.scala index 131b70caddf..065f0eaee12 100644 --- a/tests/src/test/scala/cats/tests/WordCountTest.scala +++ b/tests/src/test/scala/cats/tests/WordCountTest.scala @@ -2,7 +2,7 @@ package cats package tests import cats.data.{ Func, AppFunc, Const } -import Func.{ appFunc, appFuncU } +import Func.appFunc /* * This an example of applicative function composition. @@ -29,7 +29,7 @@ class WordCountTest extends CatsSuite { // To count words, we need to detect transitions from whitespace to non-whitespace. val countWord = - appFuncU { (c: Char) => + appFunc { (c: Char) => for { x <- get[Boolean] y = !isSpace(c) diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index 69a261c1d98..ccea93c7fe9 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -6,7 +6,6 @@ import cats.functor.{Bifunctor, Contravariant} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ -import org.scalacheck.Arbitrary import cats.kernel.laws.OrderLaws @@ -358,8 +357,6 @@ class WriterTTests extends CatsSuite { WriterT.catsDataEqForWriterT[Validated[String, ?], ListWrapper[Int], A] implicit val eq2: Eq[EitherT[WriterT[Validated[String, ?], ListWrapper[Int], ?], String, Int]] = EitherT.catsDataEqForEitherT[WriterT[Validated[String, ?], ListWrapper[Int], ?], String, Int] - implicit def arb0[A:Arbitrary]: Arbitrary[WriterT[Validated[String, ?], ListWrapper[Int], A]] = - arbitrary.catsLawsArbitraryForWriterT[Validated[String, ?], ListWrapper[Int], A] Functor[WriterT[Validated[String, ?], ListWrapper[Int], ?]] Apply[WriterT[Validated[String, ?], ListWrapper[Int], ?]]