diff --git a/core/src/main/scala/cats/Inject.scala b/core/src/main/scala/cats/InjectK.scala similarity index 55% rename from core/src/main/scala/cats/Inject.scala rename to core/src/main/scala/cats/InjectK.scala index db6e76e2181..e9b3c449d8a 100644 --- a/core/src/main/scala/cats/Inject.scala +++ b/core/src/main/scala/cats/InjectK.scala @@ -4,11 +4,11 @@ import cats.arrow.FunctionK import cats.data.EitherK /** - * Inject type class as described in "Data types a la carte" (Swierstra 2008). + * InjectK 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 +18,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] { +private[cats] sealed abstract class InjectKInstances { + implicit def catsReflexiveInjectKInstance[F[_]]: InjectK[F, F] = + new InjectK[F, F] { val inj = λ[FunctionK[F, F]](identity(_)) 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/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/docs/src/main/tut/datatypes/freemonad.md b/docs/src/main/tut/datatypes/freemonad.md index dc1d0b344f8..bdf36bdb002 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 `InjectK` 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/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/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)) } }