From b085094af16fa758599992da80d3f70daed4a296 Mon Sep 17 00:00:00 2001 From: Markus Hauck Date: Mon, 25 Apr 2016 20:06:32 +0200 Subject: [PATCH] Replace occurences of `~>` with `NaturalTransformation` --- .../main/scala/cats/arrow/NaturalTransformation.scala | 4 ++-- core/src/main/scala/cats/data/Kleisli.scala | 4 ++-- core/src/main/scala/cats/free/Coyoneda.scala | 4 +++- core/src/main/scala/cats/free/Free.scala | 7 +++---- core/src/main/scala/cats/free/FreeApplicative.scala | 8 ++++---- docs/src/main/tut/freemonad.md | 9 ++++++--- .../src/test/scala/cats/tests/FreeApplicativeTests.scala | 4 ++-- tests/src/test/scala/cats/tests/FreeTests.scala | 4 ++-- tests/src/test/scala/cats/tests/InjectTests.scala | 7 ++++--- tests/src/test/scala/cats/tests/KleisliTests.scala | 4 ++-- .../scala/cats/tests/NaturalTransformationTests.scala | 4 ++-- 11 files changed, 32 insertions(+), 27 deletions(-) diff --git a/core/src/main/scala/cats/arrow/NaturalTransformation.scala b/core/src/main/scala/cats/arrow/NaturalTransformation.scala index 87a96e92fcd..0b792bc9cfe 100644 --- a/core/src/main/scala/cats/arrow/NaturalTransformation.scala +++ b/core/src/main/scala/cats/arrow/NaturalTransformation.scala @@ -14,8 +14,8 @@ trait NaturalTransformation[F[_], G[_]] extends Serializable { self => def andThen[H[_]](f: NaturalTransformation[G, H]): NaturalTransformation[F, H] = f.compose(self) - def or[H[_]](h: H ~> G): Coproduct[F, H, ?] ~> G = - new (Coproduct[F, H, ?] ~> G) { + def or[H[_]](h: NaturalTransformation[H,G]): NaturalTransformation[Coproduct[F, H, ?],G] = + new (NaturalTransformation[Coproduct[F, H, ?],G]) { def apply[A](fa: Coproduct[F, H, A]): G[A] = fa.run match { case Xor.Left(ff) => self(ff) case Xor.Right(gg) => h(gg) diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 1fbdf1e5f73..237f6084c45 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -1,7 +1,7 @@ package cats package data -import cats.arrow.{Arrow, Choice, Split} +import cats.arrow.{Arrow, Choice, Split, NaturalTransformation} import cats.functor.{Contravariant, Strong} /** @@ -48,7 +48,7 @@ final case class Kleisli[F[_], A, B](run: A => F[B]) { self => def local[AA](f: AA => A): Kleisli[F, AA, B] = Kleisli(f.andThen(run)) - def transform[G[_]](f: F ~> G): Kleisli[G, A, B] = + def transform[G[_]](f: NaturalTransformation[F,G]): Kleisli[G, A, B] = Kleisli(a => f(run(a))) def lower(implicit F: Applicative[F]): Kleisli[F, A, F[B]] = diff --git a/core/src/main/scala/cats/free/Coyoneda.scala b/core/src/main/scala/cats/free/Coyoneda.scala index 20f9c9852d1..9afa427ca34 100644 --- a/core/src/main/scala/cats/free/Coyoneda.scala +++ b/core/src/main/scala/cats/free/Coyoneda.scala @@ -1,6 +1,8 @@ package cats package free +import cats.arrow.NaturalTransformation + /** * The dual view of the Yoneda lemma. Also a free functor on `F`. * This is isomorphic to `F` as long as `F` itself is a functor. @@ -36,7 +38,7 @@ sealed abstract class Coyoneda[F[_], A] extends Serializable { self => final def map[B](f: A => B): Aux[F, B, Pivot] = apply(fi)(f compose k) - final def transform[G[_]](f: F ~> G): Aux[G, A, Pivot] = + final def transform[G[_]](f: NaturalTransformation[F,G]): Aux[G, A, Pivot] = apply(f(fi))(k) } diff --git a/core/src/main/scala/cats/free/Free.scala b/core/src/main/scala/cats/free/Free.scala index 585463ade0e..d6a14d3a704 100644 --- a/core/src/main/scala/cats/free/Free.scala +++ b/core/src/main/scala/cats/free/Free.scala @@ -130,7 +130,7 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { * Run to completion, mapping the suspension with the given transformation at each step and * accumulating into the monad `M`. */ - final def foldMap[M[_]](f: S ~> M)(implicit M: Monad[M]): M[A] = + final def foldMap[M[_]](f: NaturalTransformation[S,M])(implicit M: Monad[M]): M[A] = step match { case Pure(a) => M.pure(a) case Suspend(s) => f(s) @@ -142,14 +142,13 @@ sealed abstract class Free[S[_], A] extends Product with Serializable { * using the given natural transformation. * Be careful if your natural transformation is effectful, effects are applied by mapSuspension. */ - final def mapSuspension[T[_]](f: S ~> T): Free[T, A] = + final def mapSuspension[T[_]](f: NaturalTransformation[S,T]): Free[T, A] = foldMap[Free[T, ?]] { new NaturalTransformation[S, Free[T, ?]] { def apply[B](fa: S[B]): Free[T, B] = Suspend(f(fa)) } }(Free.freeMonad) - final def compile[T[_]](f: S ~> T): Free[T, A] = mapSuspension(f) + final def compile[T[_]](f: NaturalTransformation[S,T]): Free[T, A] = mapSuspension(f) } - diff --git a/core/src/main/scala/cats/free/FreeApplicative.scala b/core/src/main/scala/cats/free/FreeApplicative.scala index ad9c57aac48..e5a9268ac8f 100644 --- a/core/src/main/scala/cats/free/FreeApplicative.scala +++ b/core/src/main/scala/cats/free/FreeApplicative.scala @@ -27,7 +27,7 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable /** Interprets/Runs the sequence of operations using the semantics of Applicative G * Tail recursive only if G provides tail recursive interpretation (ie G is FreeMonad) */ - final def foldMap[G[_]](f: F ~> G)(implicit G: Applicative[G]): G[A] = + final def foldMap[G[_]](f: NaturalTransformation[F,G])(implicit G: Applicative[G]): G[A] = this match { case Pure(a) => G.pure(a) case Ap(pivot, fn) => G.map2(f(pivot), fn.foldMap(f))((a, g) => g(a)) @@ -40,7 +40,7 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable foldMap(NaturalTransformation.id[F]) /** Interpret this algebra into another FreeApplicative */ - final def compile[G[_]](f: F ~> G): FA[G, A] = + final def compile[G[_]](f: NaturalTransformation[F,G]): FA[G, A] = foldMap[FA[G, ?]] { new NaturalTransformation[F, FA[G, ?]] { def apply[B](fa: F[B]): FA[G, B] = lift(f(fa)) @@ -48,8 +48,8 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable } /** Interpret this algebra into a Monoid */ - final def analyze[M:Monoid](f: F ~> λ[α => M]): M = - foldMap[Const[M, ?]](new (F ~> Const[M, ?]) { + final def analyze[M:Monoid](f: NaturalTransformation[F,λ[α => M]]): M = + foldMap[Const[M, ?]](new (NaturalTransformation[F,Const[M, ?]]) { def apply[X](x: F[X]): Const[M,X] = Const(f(x)) }).getConst diff --git a/docs/src/main/tut/freemonad.md b/docs/src/main/tut/freemonad.md index dbd2d1e4479..c8522434620 100644 --- a/docs/src/main/tut/freemonad.md +++ b/docs/src/main/tut/freemonad.md @@ -162,12 +162,15 @@ DSL. By itself, this DSL only represents a sequence of operations To do this, we will use a *natural transformation* between type containers. Natural transformations go between types like `F[_]` and -`G[_]` (this particular transformation would be written as `F ~> G`). +`G[_]` (this particular transformation would be written as +`NaturalTransformation[F,G]` or as done here using the symbolic +alternative as `F ~> G`). In our case, we will use a simple mutable map to represent our key value store: ```tut:silent +import cats.arrow.NaturalTransformation import cats.{Id, ~>} import scala.collection.mutable @@ -238,7 +241,7 @@ recursive structure by: This operation is called `Free.foldMap`: ```scala -final def foldMap[M[_]](f: S ~> M)(M: Monad[M]): M[A] = ... +final def foldMap[M[_]](f: NaturalTransformation[S,M])(M: Monad[M]): M[A] = ... ``` `M` must be a `Monad` to be flattenable (the famous monoid aspect @@ -378,7 +381,7 @@ object ConsoleCatsInterpreter extends (Interact ~> Id) { } } -object InMemoryDatasourceInterpreter extends (DataOp ~> Id) { +object InMemoryDatasourceInterpreter extends NaturalTransformation[DataOp,Id] { private[this] val memDataSet = new ListBuffer[String] diff --git a/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala b/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala index c8f6dd8861c..e862a161f30 100644 --- a/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala +++ b/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala @@ -98,7 +98,7 @@ class FreeApplicativeTests extends CatsSuite { type Tracked[A] = State[String, A] - val f: Foo ~> Tracked = new (Foo ~> Tracked) { + val f: NaturalTransformation[Foo,Tracked] = new NaturalTransformation[Foo,Tracked] { def apply[A](fa: Foo[A]): Tracked[A] = State[String, A]{ s0 => (s0 + fa.toString + ";", fa.getA) } @@ -121,7 +121,7 @@ class FreeApplicativeTests extends CatsSuite { val z = Apply[Dsl].map2(x, y)((_, _) => ()) - val asString: Id ~> λ[α => String] = new (Id ~> λ[α => String]) { + val asString: NaturalTransformation[Id,λ[α => String]] = new NaturalTransformation[Id,λ[α => String]] { def apply[A](a: A): String = a.toString } diff --git a/tests/src/test/scala/cats/tests/FreeTests.scala b/tests/src/test/scala/cats/tests/FreeTests.scala index 56fe308ac23..3d92def5ec3 100644 --- a/tests/src/test/scala/cats/tests/FreeTests.scala +++ b/tests/src/test/scala/cats/tests/FreeTests.scala @@ -56,7 +56,7 @@ class FreeTests extends CatsSuite { z <- if (j<10000) a(j) else Free.pure[FTestApi, Int](j) } yield z - def runner: FTestApi ~> Id = new (FTestApi ~> Id) { + def runner: NaturalTransformation[FTestApi,Id] = new NaturalTransformation[FTestApi,Id] { def apply[A](fa: FTestApi[A]): Id[A] = fa match { case TB(i) => i+1 } @@ -77,7 +77,7 @@ object FreeTests extends FreeTestsInstances { } sealed trait FreeTestsInstances { - val headOptionU: List ~> Option = new (List ~> Option) { + val headOptionU: NaturalTransformation[List,Option] = new NaturalTransformation[List,Option] { def apply[A](fa: List[A]): Option[A] = fa.headOption } diff --git a/tests/src/test/scala/cats/tests/InjectTests.scala b/tests/src/test/scala/cats/tests/InjectTests.scala index d174180d9c2..6b42732d350 100644 --- a/tests/src/test/scala/cats/tests/InjectTests.scala +++ b/tests/src/test/scala/cats/tests/InjectTests.scala @@ -1,6 +1,7 @@ package cats package tests +import cats.arrow.NaturalTransformation import cats.data.{Xor, Coproduct} import cats.free.{Free, Inject,:<:} import org.scalacheck._ @@ -39,19 +40,19 @@ class InjectTests extends CatsSuite { implicit def test2Arbitrary[A](implicit seqArb: Arbitrary[Int], intAArb : Arbitrary[Int => A]): Arbitrary[Test2[A]] = Arbitrary(for {s <- seqArb.arbitrary; f <- intAArb.arbitrary} yield Test2(s, f)) - object Test1Interpreter extends (Test1Algebra ~> Id) { + object Test1Interpreter extends NaturalTransformation[Test1Algebra,Id] { override def apply[A](fa: Test1Algebra[A]): Id[A] = fa match { case Test1(k, h) => h(k) } } - object Test2Interpreter extends (Test2Algebra ~> Id) { + object Test2Interpreter extends NaturalTransformation[Test2Algebra,Id] { override def apply[A](fa: Test2Algebra[A]): Id[A] = fa match { case Test2(k, h) => h(k) } } - val coProductInterpreter: T ~> Id = Test1Interpreter or Test2Interpreter + val coProductInterpreter: NaturalTransformation[T,Id] = Test1Interpreter or Test2Interpreter val x: Free[T, Int] = Free.inject[Test1Algebra, T](Test1(1, identity)) diff --git a/tests/src/test/scala/cats/tests/KleisliTests.scala b/tests/src/test/scala/cats/tests/KleisliTests.scala index 959bba9776a..1d8cb5edf00 100644 --- a/tests/src/test/scala/cats/tests/KleisliTests.scala +++ b/tests/src/test/scala/cats/tests/KleisliTests.scala @@ -1,7 +1,7 @@ package cats package tests -import cats.arrow.{Arrow, Choice, Split} +import cats.arrow.{Arrow, Choice, Split, NaturalTransformation} import cats.data.{Kleisli, Reader} import cats.functor.{Contravariant, Strong} import cats.laws.discipline._ @@ -121,7 +121,7 @@ class KleisliTests extends CatsSuite { test("transform") { val opt = Kleisli { (x: Int) => Option(x.toDouble) } - val optToList = new (Option ~> List) { def apply[A](fa: Option[A]): List[A] = fa.toList } + val optToList = new NaturalTransformation[Option,List] { def apply[A](fa: Option[A]): List[A] = fa.toList } val list = opt.transform(optToList) val is = 0.to(10).toList diff --git a/tests/src/test/scala/cats/tests/NaturalTransformationTests.scala b/tests/src/test/scala/cats/tests/NaturalTransformationTests.scala index b46fa0026bc..3c69bc8a577 100644 --- a/tests/src/test/scala/cats/tests/NaturalTransformationTests.scala +++ b/tests/src/test/scala/cats/tests/NaturalTransformationTests.scala @@ -28,11 +28,11 @@ class NaturalTransformationTests extends CatsSuite { case class Test2[A](v : A) extends Test2Algebra[A] - object Test1NT extends (Test1Algebra ~> Id) { + object Test1NT extends NaturalTransformation[Test1Algebra,Id] { override def apply[A](fa: Test1Algebra[A]): Id[A] = fa.v } - object Test2NT extends (Test2Algebra ~> Id) { + object Test2NT extends NaturalTransformation[Test2Algebra,Id] { override def apply[A](fa: Test2Algebra[A]): Id[A] = fa.v }