From e03050956d0f6a27ca1bb3e2213ad923a18552bb Mon Sep 17 00:00:00 2001 From: Lloyd Date: Fri, 19 May 2017 10:55:20 +0900 Subject: [PATCH] Fix annotations being passed from trait to generated companion --- README.md | 38 +++++++++------- core/src/main/scala/diesel/diesel.scala | 4 +- .../scala/diesel/internal/DieselImpl.scala | 5 ++- .../diesel/KtransAnnotationCompile.scala | 4 +- .../src/main/scala/readme/DieselDemo.scala | 44 +++++++++++++++++++ .../scala/readme/KTransDemo.scala | 0 .../src/test/scala/readme/DieselDemo.scala | 44 ------------------- 7 files changed, 74 insertions(+), 65 deletions(-) create mode 100644 examples/src/main/scala/readme/DieselDemo.scala rename examples/src/{test => main}/scala/readme/KTransDemo.scala (100%) delete mode 100644 examples/src/test/scala/readme/DieselDemo.scala diff --git a/README.md b/README.md index 328ada1..6193306 100755 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ The `@diesel` annotation that cuts out the boilerplate associated with writing c The Dsl can be accessed directly from the companion object if you import a converter located in `ops` (customisable by passing a name to the annotation as an argument). This are useful when you need to compose multiple DSLs in the context of `F[_]`, but do not want to name all the interpreter parameters. +Note that this can be used along-side `@ktrans`. + ### Example: ```scala @@ -26,8 +28,8 @@ object DieselDemo { // Declare your DSL @diesel trait Maths[F[_]] { - def int(i: Int): F[Int] - def add(l: F[Int], r: F[Int]): F[Int] + def times(l: Int, r: Int): F[Int] + def add(l: Int, r: Int): F[Int] } @diesel @@ -37,32 +39,34 @@ object DieselDemo { // Import companion-to-interpreter aliasing sugar import Maths.ops._, Logger.ops._ - def addAndLog[F[_]: Monad: Maths: Logger](x: Int, y: Int): F[Int] = { + def prog[F[_]: Monad: Maths: Logger](x: Int, y: Int): F[Int] = { for { - r <- Maths.add(Maths.int(x), Maths.int(y)) - _ <- Logger.info(s"result $r") - } yield r + p <- Maths.times(x, y) + _ <- Logger.info(s"Product: $p") + s <- Maths.add(x, y) + _ <- Logger.info(s"Sum: $s") + } yield p + s } def main(args: Array[String]): Unit = { // Wire in our interpreters implicit val mathsInterp = new Maths[Id] { - def int(a: Int) = a - def add(a: Id[Int], b: Id[Int]) = a + b + def times(l: Int, r: Int) = l * r + def add(l: Int, r: Int) = l + r } implicit val loggingInterp = new Logger[Id] { def info(msg: String) = println(msg) } - addAndLog[Id](1, 2) - () + val _ = prog[Id](1, 2) } } /* [info] Running DieselDemo -result 3 +Product: 2 +Sum: 3 */ ``` @@ -79,8 +83,8 @@ All of the above examples use a pure KVS interpreter :) ```scala @diesel trait Maths[F[_]] { - def int(i: Int): F[Int] - def add(l: F[Int], r: F[Int]): F[Int] + def times(l: Int, r: Int): F[Int] + def add(l: Int, r: Int): F[Int] } ``` @@ -89,8 +93,8 @@ is expanded approximately into ```scala // Your algebra. Implement by providing a concrete F and you have your interpreter trait Maths[F[_]] { - def int(i: Int): F[Int] - def add(l: F[Int], r: F[Int]): F[Int] + def times(l: Int, r: Int): F[Int] + def add(l: Int, r: Int): F[Int] } // Helper methods will be added to the algebra's companion object (one will be created if there isn't one yet) @@ -111,7 +115,9 @@ object Maths { There is also a handy `@ktrans` annotation that adds a `transformK` method to a trait that is parameterised by a Kind that takes 1 type parameter. It's useful when you want to transform any given implementation of that trait for `F[_]` into one - that implements it on `G[_]` + that implements it on `G[_]`. + +Note that this can be used along-side `@diesel`. ### Example diff --git a/core/src/main/scala/diesel/diesel.scala b/core/src/main/scala/diesel/diesel.scala index f8a315e..d6d0d3b 100644 --- a/core/src/main/scala/diesel/diesel.scala +++ b/core/src/main/scala/diesel/diesel.scala @@ -21,6 +21,7 @@ import scala.annotation.compileTimeOnly * | // Declare our DSL * | @diesel * | trait Maths[G[_]] { + * | def times(l: Int, r: Int): G[Int] * | def add(l: Int, r: Int): G[Int] * | } * | @diesel @@ -39,7 +40,8 @@ import scala.annotation.compileTimeOnly * | } * * scala> implicit val MathsIdInterp = new Maths[Id] { - * | def add(l: Int, r: Int) = l + r + * | def times(l: Int, r: Int) = l * r + * | def add(l: Int, r: Int) = l + r * | } * * scala> implicit val LoggerIdInterp = new Logger[Id] { diff --git a/core/src/main/scala/diesel/internal/DieselImpl.scala b/core/src/main/scala/diesel/internal/DieselImpl.scala index 22d9d87..ba55dbc 100644 --- a/core/src/main/scala/diesel/internal/DieselImpl.scala +++ b/core/src/main/scala/diesel/internal/DieselImpl.scala @@ -24,7 +24,7 @@ object DieselImpl { Term.Block( Seq( extracted.underlying, - q"""..${objectModsOnly(mods)} object ${Term.Name(tname.value)} { + q"""..${modsForGeneratedCompanion(mods)} object ${Term.Name(tname.value)} { $algebraAlias $singletonAlias $applyMethod @@ -65,7 +65,8 @@ object DieselImpl { } } - private def objectModsOnly(ms: Seq[Mod]): Seq[Mod] = ms.filter { + private def modsForGeneratedCompanion(ms: Seq[Mod]): Seq[Mod] = ms.filter { + case _: Mod.Annot => false case mod"final" => false case mod"abstract" => false case mod"sealed" => false diff --git a/core/src/test/scala/diesel/KtransAnnotationCompile.scala b/core/src/test/scala/diesel/KtransAnnotationCompile.scala index eaac00f..8649320 100644 --- a/core/src/test/scala/diesel/KtransAnnotationCompile.scala +++ b/core/src/test/scala/diesel/KtransAnnotationCompile.scala @@ -5,7 +5,7 @@ import cats.kernel.Monoid object KtransAnnotationCompileTests { - @ktrans + @ktrans @diesel trait Trait1[F[_]] { val vlaThing, vlaThing2: F[Int] def noArg: F[Int] @@ -19,7 +19,7 @@ object KtransAnnotationCompileTests { private[diesel] def packPriv(p: Byte): F[Byte] } - @ktrans + @diesel @ktrans trait TraitWithComp[F[_]] { def noArg: F[Int] def ser[A: Monoid](k: String, o: A): F[Unit] diff --git a/examples/src/main/scala/readme/DieselDemo.scala b/examples/src/main/scala/readme/DieselDemo.scala new file mode 100644 index 0000000..c1aa083 --- /dev/null +++ b/examples/src/main/scala/readme/DieselDemo.scala @@ -0,0 +1,44 @@ +package readme + +import diesel._, cats._, cats.implicits._ + +object DieselDemo { + + // Declare your DSL + @diesel + trait Maths[F[_]] { + def times(l: Int, r: Int): F[Int] + def add(l: Int, r: Int): F[Int] + } + + @diesel + trait Logger[F[_]] { + def info(s: String): F[Unit] + } + + // Import companion-to-interpreter aliasing sugar + import Maths.ops._, Logger.ops._ + def prog[F[_]: Monad: Maths: Logger](x: Int, y: Int): F[Int] = { + for { + p <- Maths.times(x, y) + _ <- Logger.info(s"Product: $p") + s <- Maths.add(x, y) + _ <- Logger.info(s"Sum: $s") + } yield p + s + } + + def main(args: Array[String]): Unit = { + + // Wire in our interpreters + implicit val mathsInterp = new Maths[Id] { + def times(l: Int, r: Int) = l * r + def add(l: Int, r: Int) = l + r + } + implicit val loggingInterp = new Logger[Id] { + def info(msg: String) = println(msg) + } + + val _ = prog[Id](1, 2) + } + +} \ No newline at end of file diff --git a/examples/src/test/scala/readme/KTransDemo.scala b/examples/src/main/scala/readme/KTransDemo.scala similarity index 100% rename from examples/src/test/scala/readme/KTransDemo.scala rename to examples/src/main/scala/readme/KTransDemo.scala diff --git a/examples/src/test/scala/readme/DieselDemo.scala b/examples/src/test/scala/readme/DieselDemo.scala deleted file mode 100644 index c611969..0000000 --- a/examples/src/test/scala/readme/DieselDemo.scala +++ /dev/null @@ -1,44 +0,0 @@ -package readme - -import diesel._ -import _root_.cats._, _root_.cats.implicits._ - -object DieselDemo { - - // Declare your DSL - @diesel - trait Maths[F[_]] { - def int(i: Int): F[Int] - def add(l: F[Int], r: F[Int]): F[Int] - } - - @ktrans @diesel - trait Logger[F[_]] { - def info(s: String): F[Unit] - } - - // Use the Dsl wrapping methods - import Maths.ops._, Logger.ops._ - def addAndLog[F[_]: Monad: Maths: Logger](x: Int, y: Int): F[Int] = { - for { - r <- Maths.add(Maths.int(x), Maths.int(y)) - _ <- Logger.info(s"result $r") - } yield r - } - - def main(args: Array[String]): Unit = { - - // Wire in our interpreters - implicit val mathsInterp = new Maths[Id] { - def int(a: Int) = a - def add(a: Id[Int], b: Id[Int]) = a + b - } - implicit val loggingInterp = new Logger[Id] { - def info(msg: String) = println(msg) - } - - addAndLog[Id](1, 2) - () - } - -} \ No newline at end of file