From 09972d809febf19fc97aad4015bfe087bd3c503d Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Mon, 26 Apr 2021 10:50:07 +0200 Subject: [PATCH 1/8] Refactor KernelBoiler, use SAM instances when possible Make it a bit more readable by formatting constraints on a new line. --- project/KernelBoiler.scala | 322 ++++++++++++++++++++----------------- 1 file changed, 170 insertions(+), 152 deletions(-) diff --git a/project/KernelBoiler.scala b/project/KernelBoiler.scala index 207a2b5ec7..2beb7c7aa3 100644 --- a/project/KernelBoiler.scala +++ b/project/KernelBoiler.scala @@ -1,4 +1,3 @@ -import KernelBoiler.TemplateVals import sbt._ /** @@ -82,40 +81,40 @@ object KernelBoiler { abstract class TemplatedBlock(tv: TemplateVals) { import tv._ - def constraints(constraint: String) = - synTypes.map(tpe => s"${tpe}: ${constraint}[${tpe}]").mkString(", ") + def constraints(constraint: String): String = + synTypes.map(tpe => s"$tpe: $constraint[$tpe]").mkString(", ") - def tuple(results: TraversableOnce[String]) = { + def tuple(results: TraversableOnce[String]): String = { val resultsVec = results.toVector val a = synTypes.size val r = s"${0.until(a).map(i => resultsVec(i)).mkString(", ")}" if (a == 1) "Tuple1(" ++ r ++ ")" - else s"(${r})" + else s"($r)" } def tupleNHeader = s"Tuple${synTypes.size}" - def binMethod(name: String) = + def binMethod(name: String): Iterator[String] = synTypes.zipWithIndex.iterator.map { case (tpe, i) => val j = i + 1 - s"${tpe}.${name}(x._${j}, y._${j})" + s"$tpe.$name(x._$j, y._$j)" } - def binTuple(name: String) = + def binTuple(name: String): String = tuple(binMethod(name)) - def unaryTuple(name: String) = { - val m = synTypes.zipWithIndex.map { case (tpe, i) => s"${tpe}.${name}(x._${i + 1})" } + def unaryTuple(name: String): String = { + val m = synTypes.zipWithIndex.map { case (tpe, i) => s"$tpe.$name(x._${i + 1})" } tuple(m) } - def unaryMethod(name: String) = + def unaryMethod(name: String): Iterator[String] = synTypes.zipWithIndex.iterator.map { case (tpe, i) => s"$tpe.$name(x._${i + 1})" } - def nullaryTuple(name: String) = { - val m = synTypes.map(tpe => s"${tpe}.${name}") + def nullaryTuple(name: String): String = { + val m = synTypes.map(tpe => s"$tpe.$name") tuple(m) } @@ -142,26 +141,23 @@ object KernelBoiler { import tv._ def content = block""" - | implicit def catsKernelStdCommutativeGroupForTuple${arity}[${`A..N`}](implicit ${constraints( - "CommutativeGroup" - )}): CommutativeGroup[${`(A..N)`}] = - | new CommutativeGroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | } - | implicit def catsKernelStdOrderForTuple${arity}[${`A..N`}](implicit ${constraints("Order")}): Order[${`(A..N)`}] = - | new Order[${`(A..N)`}] { - | def compare(x: ${`(A..N)`}, y: ${`(A..N)`}): Int = - | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0) - | } - | implicit def catsKernelStdBoundedSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints( - "BoundedSemilattice" - )}): BoundedSemilattice[${`(A..N)`}] = - | new BoundedSemilattice[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | implicit def catsKernelStdCommutativeGroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("CommutativeGroup")} + | ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} + | } + | implicit def catsKernelStdOrderForTuple$arity[${`A..N`}]( + | implicit ${constraints("Order")} + | ): Order[${`(A..N)`}] = (x, y) => + | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0) + | implicit def catsKernelStdBoundedSemilatticeForTuple$arity[${`A..N`}]( + | implicit ${constraints("BoundedSemilattice")} + | ): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | }""" } ), InstanceDef( @@ -172,38 +168,36 @@ object KernelBoiler { import tv._ def content = block""" - | implicit def catsKernelStdSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints( - "Semilattice" - )}): Semilattice[${`(A..N)`}] = - | new Semilattice[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | } - | implicit def catsKernelStdCommutativeMonoidForTuple${arity}[${`A..N`}](implicit ${constraints( - "CommutativeMonoid" - )}): CommutativeMonoid[${`(A..N)`}] = - | new CommutativeMonoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | } - | implicit def catsKernelStdGroupForTuple${arity}[${`A..N`}](implicit ${constraints("Group")}): Group[${`(A..N)`}] = - | new Group[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | } - | implicit def catsKernelStdHashForTuple${arity}[${`A..N`}](implicit ${constraints("Hash")}): Hash[${`(A..N)`}] = - | new Hash[${`(A..N)`}] { - | def hash(x: ${`(A..N)`}): Int = ${unaryMethod("hash") - .mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() - | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")} - | } - | implicit def catsKernelStdPartialOrderForTuple${arity}[${`A..N`}](implicit ${constraints( - "PartialOrder" - )}): PartialOrder[${`(A..N)`}] = - | new PartialOrder[${`(A..N)`}] { - | def partialCompare(x: ${`(A..N)`}, y: ${`(A..N)`}): Double = - | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0) - | }""" + | implicit def catsKernelStdSemilatticeForTuple$arity[${`A..N`}]( + | implicit ${constraints("Semilattice")} + | ): Semilattice[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + | implicit def catsKernelStdCommutativeMonoidForTuple$arity[${`A..N`}]( + | implicit ${constraints("CommutativeMonoid")} + | ): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | } + | implicit def catsKernelStdGroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("Group")} + | ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} + | } + | implicit def catsKernelStdHashForTuple$arity[${`A..N`}]( + | implicit ${constraints("Hash")} + | ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] { + | def hash(x: ${`(A..N)`}): Int = + | ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() + | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = + | ${binMethod("eqv").mkString(" && ")} + | } + | implicit def catsKernelStdPartialOrderForTuple$arity[${`A..N`}]( + | implicit ${constraints("PartialOrder")} + | ): PartialOrder[${`(A..N)`}] = (x, y) => + | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0) + |""" } ), InstanceDef( @@ -214,21 +208,20 @@ object KernelBoiler { import tv._ def content = block""" - | implicit def catsKernelStdBandForTuple${arity}[${`A..N`}](implicit ${constraints("Band")}): Band[${`(A..N)`}] = - | new Band[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | } - | implicit def catsKernelStdCommutativeSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints( - "CommutativeSemigroup" - )}): CommutativeSemigroup[${`(A..N)`}] = - | new CommutativeSemigroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | } - | implicit def catsKernelStdMonoidForTuple${arity}[${`A..N`}](implicit ${constraints("Monoid")}): Monoid[${`(A..N)`}] = - | new Monoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | implicit def catsKernelStdBandForTuple$arity[${`A..N`}]( + | implicit ${constraints("Band")} + | ): Band[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + | implicit def catsKernelStdCommutativeSemigroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("CommutativeSemigroup")} + | ): CommutativeSemigroup[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + | implicit def catsKernelStdMonoidForTuple$arity[${`A..N`}]( + | implicit ${constraints("Monoid")} + | ): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | }""" } ), InstanceDef( @@ -239,14 +232,15 @@ object KernelBoiler { import tv._ def content = block""" - | implicit def catsKernelStdSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints("Semigroup")}): Semigroup[${`(A..N)`}] = - | new Semigroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | } - | implicit def catsKernelStdEqForTuple${arity}[${`A..N`}](implicit ${constraints("Eq")}): Eq[${`(A..N)`}] = - | new Eq[${`(A..N)`}] { - | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")} - | }""" + | implicit def catsKernelStdSemigroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("Semigroup")} + | ): Semigroup[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + | implicit def catsKernelStdEqForTuple$arity[${`A..N`}]( + | implicit ${constraints("Eq")} + | ): Eq[${`(A..N)`}] = (x, y) => + | ${binMethod("eqv").mkString(" && ")} + |""" } ), InstanceDef( @@ -255,9 +249,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelBandForTuple${arity}[${`A..N`}](implicit ${constraints("Band")}): Band[${`(A..N)`}] = new Band[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | }""" + block""" + | implicit def catsKernelBandForTuple$arity[${`A..N`}]( + | implicit ${constraints("Band")} + | ): Band[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + |""" } ), InstanceDef( @@ -266,12 +263,13 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelBoundedSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints( - "BoundedSemilattice" - )}): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + block""" + | implicit def catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}]( + | implicit ${constraints("BoundedSemilattice")} + | ): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | }""" } ), InstanceDef( @@ -280,13 +278,14 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelCommutativeGroupForTuple${arity}[${`A..N`}](implicit ${constraints( - "CommutativeGroup" - )}): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | }""" + block""" + | implicit def catsKernelCommutativeGroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("CommutativeGroup")} + | ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} + | }""" } ), InstanceDef( @@ -295,12 +294,13 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelCommutativeMonoidForTuple${arity}[${`A..N`}](implicit ${constraints( - "CommutativeMonoid" - )}): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + block""" + | implicit def catsKernelCommutativeMonoidForTuple$arity[${`A..N`}]( + | implicit ${constraints("CommutativeMonoid")} + | ): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | }""" } ), InstanceDef( @@ -309,11 +309,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelCommutativeSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints( - "CommutativeSemigroup" - )}): CommutativeSemigroup[${`(A..N)`}] = new CommutativeSemigroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | }""" + block""" + | implicit def catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("CommutativeSemigroup")} + | ): CommutativeSemigroup[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + |""" } ), InstanceDef( @@ -322,9 +323,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelEqForTuple${arity}[${`A..N`}](implicit ${constraints("Eq")}): Eq[${`(A..N)`}] = new Eq[${`(A..N)`}] { - | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")} - | }""" + block""" + | implicit def catsKernelEqForTuple$arity[${`A..N`}]( + | implicit ${constraints("Eq")} + | ): Eq[${`(A..N)`}] = (x, y) => + | ${binMethod("eqv").mkString(" && ")} + |""" } ), InstanceDef( @@ -333,11 +337,14 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelGroupForTuple${arity}[${`A..N`}](implicit ${constraints("Group")}): Group[${`(A..N)`}] = new Group[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | }""" + block""" + | implicit def catsKernelGroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("Group")} + | ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} + | }""" } ), InstanceDef( @@ -346,11 +353,15 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelHashForTuple${arity}[${`A..N`}](implicit ${constraints("Hash")}): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] { - | def hash(x: ${`(A..N)`}): Int = ${unaryMethod("hash") - .mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() - | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = ${binMethod("eqv").mkString(" && ")} - | }""" + block""" + | implicit def catsKernelHashForTuple$arity[${`A..N`}]( + | implicit ${constraints("Hash")} + | ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] { + | def hash(x: ${`(A..N)`}): Int = + | ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() + | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = + | ${binMethod("eqv").mkString(" && ")} + | }""" } ), InstanceDef( @@ -359,10 +370,13 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelMonoidForTuple${arity}[${`A..N`}](implicit ${constraints("Monoid")}): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + block""" + | implicit def catsKernelMonoidForTuple$arity[${`A..N`}]( + | implicit ${constraints("Monoid")} + | ): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] { + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} + | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} + | }""" } ), InstanceDef( @@ -371,10 +385,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelOrderForTuple${arity}[${`A..N`}](implicit ${constraints("Order")}): Order[${`(A..N)`}] = new Order[${`(A..N)`}] { - | def compare(x: ${`(A..N)`}, y: ${`(A..N)`}): Int = - | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0) - | }""" + block""" + | implicit def catsKernelOrderForTuple$arity[${`A..N`}]( + | implicit ${constraints("Order")} + | ): Order[${`(A..N)`}] = (x, y) => + | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0) + |""" } ), InstanceDef( @@ -383,12 +399,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelPartialOrderForTuple${arity}[${`A..N`}](implicit ${constraints( - "PartialOrder" - )}): PartialOrder[${`(A..N)`}] = new PartialOrder[${`(A..N)`}] { - | def partialCompare(x: ${`(A..N)`}, y: ${`(A..N)`}): Double = - | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0) - | }""" + block""" + | implicit def catsKernelPartialOrderForTuple$arity[${`A..N`}]( + | implicit ${constraints("PartialOrder")} + | ): PartialOrder[${`(A..N)`}] = (x, y) => + | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0) + |""" } ), InstanceDef( @@ -397,11 +413,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelSemigroupForTuple${arity}[${`A..N`}](implicit ${constraints( - "Semigroup" - )}): Semigroup[${`(A..N)`}] = new Semigroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | }""" + block""" + | implicit def catsKernelSemigroupForTuple$arity[${`A..N`}]( + | implicit ${constraints("Semigroup")} + | ): Semigroup[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + |""" } ), InstanceDef( @@ -410,11 +427,12 @@ object KernelBoiler { new TemplatedBlock(tv) { import tv._ def content = - block"""| implicit def catsKernelSemilatticeForTuple${arity}[${`A..N`}](implicit ${constraints( - "Semilattice" - )}): Semilattice[${`(A..N)`}] = new Semilattice[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | }""" + block""" + | implicit def catsKernelSemilatticeForTuple$arity[${`A..N`}]( + | implicit ${constraints("Semilattice")} + | ): Semilattice[${`(A..N)`}] = (x, y) => + | ${binTuple("combine")} + |""" } ) ) From 5b7bd814a48db01e66863588e47804b0f755e82d Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Wed, 28 Apr 2021 00:46:27 +0200 Subject: [PATCH 2/8] Use instance constructors instead of SAM types Due to limitations in Scala 2 SAM types often end up generating classes after all. `instance` constructors don't suffer from this issue and also let us handle type classes with multiple abstract methods. --- .../scala/cats/kernel/CommutativeGroup.scala | 10 ++ kernel/src/main/scala/cats/kernel/Group.scala | 10 ++ kernel/src/main/scala/cats/kernel/Hash.scala | 12 +- project/KernelBoiler.scala | 152 ++++++++---------- 4 files changed, 97 insertions(+), 87 deletions(-) diff --git a/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala b/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala index 441ee2fcf1..b83cffdade 100644 --- a/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala +++ b/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala @@ -14,4 +14,14 @@ object CommutativeGroup extends GroupFunctions[CommutativeGroup] { * Access an implicit `CommutativeGroup[A]`. */ @inline final def apply[A](implicit ev: CommutativeGroup[A]): CommutativeGroup[A] = ev + + /** + * Create a `CommutativeGroup` instance from the given inverse and combine functions and empty value. + */ + @inline def instance[A](emp: A, inv: A => A, cmb: (A, A) => A): CommutativeGroup[A] = + new CommutativeGroup[A] { + val empty = emp + def inverse(a: A) = inv(a) + def combine(x: A, y: A) = cmb(x, y) + } } diff --git a/kernel/src/main/scala/cats/kernel/Group.scala b/kernel/src/main/scala/cats/kernel/Group.scala index 785263bce7..d6bd693d43 100644 --- a/kernel/src/main/scala/cats/kernel/Group.scala +++ b/kernel/src/main/scala/cats/kernel/Group.scala @@ -74,4 +74,14 @@ object Group extends GroupFunctions[Group] { * Access an implicit `Group[A]`. */ @inline final def apply[A](implicit ev: Group[A]): Group[A] = ev + + /** + * Create a `Group` instance from the given inverse and combine functions and empty value. + */ + @inline def instance[A](emp: A, inv: A => A, cmb: (A, A) => A): Group[A] = + new Group[A] { + val empty = emp + def inverse(a: A) = inv(a) + def combine(x: A, y: A) = cmb(x, y) + } } diff --git a/kernel/src/main/scala/cats/kernel/Hash.scala b/kernel/src/main/scala/cats/kernel/Hash.scala index 87b2917e38..fe8f4f2a32 100644 --- a/kernel/src/main/scala/cats/kernel/Hash.scala +++ b/kernel/src/main/scala/cats/kernel/Hash.scala @@ -54,11 +54,17 @@ object Hash extends HashFunctions[Hash] { def eqv(x: A, y: A) = x == y } + /** + * Create a `Hash` instance from the given hash and equality functions. + */ + @inline def instance[A](h: A => Int, e: (A, A) => Boolean): Hash[A] = + new Hash[A] { + def hash(x: A) = h(x) + def eqv(x: A, y: A) = e(x, y) + } } trait HashToHashingConversion { implicit def catsKernelHashToHashing[A](implicit ev: Hash[A]): Hashing[A] = - new Hashing[A] { - override def hash(x: A): Int = ev.hash(x) - } + ev.hash(_) } diff --git a/project/KernelBoiler.scala b/project/KernelBoiler.scala index 2beb7c7aa3..ee11019fa4 100644 --- a/project/KernelBoiler.scala +++ b/project/KernelBoiler.scala @@ -143,21 +143,17 @@ object KernelBoiler { block""" | implicit def catsKernelStdCommutativeGroupForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeGroup")} - | ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | } + | ): CommutativeGroup[${`(A..N)`}] = + | Semigroup.catsKernelCommutativeGroupForTuple$arity[${`A..N`}] | implicit def catsKernelStdOrderForTuple$arity[${`A..N`}]( | implicit ${constraints("Order")} - | ): Order[${`(A..N)`}] = (x, y) => - | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0) + | ): Order[${`(A..N)`}] = + | Eq.catsKernelOrderForTuple$arity[${`A..N`}] | implicit def catsKernelStdBoundedSemilatticeForTuple$arity[${`A..N`}]( | implicit ${constraints("BoundedSemilattice")} - | ): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | ): BoundedSemilattice[${`(A..N)`}] = + | Semigroup.catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}] + |""" } ), InstanceDef( @@ -170,33 +166,24 @@ object KernelBoiler { block""" | implicit def catsKernelStdSemilatticeForTuple$arity[${`A..N`}]( | implicit ${constraints("Semilattice")} - | ): Semilattice[${`(A..N)`}] = (x, y) => - | ${binTuple("combine")} + | ): Semilattice[${`(A..N)`}] = + | Semigroup.catsKernelSemilatticeForTuple$arity[${`A..N`}] | implicit def catsKernelStdCommutativeMonoidForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeMonoid")} - | ): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | } + | ): CommutativeMonoid[${`(A..N)`}] = + | Semigroup.catsKernelCommutativeMonoidForTuple$arity[${`A..N`}] | implicit def catsKernelStdGroupForTuple$arity[${`A..N`}]( | implicit ${constraints("Group")} - | ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | } + | ): Group[${`(A..N)`}] = + | Semigroup.catsKernelGroupForTuple$arity[${`A..N`}] | implicit def catsKernelStdHashForTuple$arity[${`A..N`}]( | implicit ${constraints("Hash")} - | ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] { - | def hash(x: ${`(A..N)`}): Int = - | ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() - | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = - | ${binMethod("eqv").mkString(" && ")} - | } + | ): Hash[${`(A..N)`}] = + | Eq.catsKernelHashForTuple$arity[${`A..N`}] | implicit def catsKernelStdPartialOrderForTuple$arity[${`A..N`}]( | implicit ${constraints("PartialOrder")} - | ): PartialOrder[${`(A..N)`}] = (x, y) => - | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0) + | ): PartialOrder[${`(A..N)`}] = + | Eq.catsKernelPartialOrderForTuple$arity[${`A..N`}] |""" } ), @@ -210,18 +197,17 @@ object KernelBoiler { block""" | implicit def catsKernelStdBandForTuple$arity[${`A..N`}]( | implicit ${constraints("Band")} - | ): Band[${`(A..N)`}] = (x, y) => - | ${binTuple("combine")} + | ): Band[${`(A..N)`}] = + | Semigroup.catsKernelBandForTuple$arity[${`A..N`}] | implicit def catsKernelStdCommutativeSemigroupForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeSemigroup")} - | ): CommutativeSemigroup[${`(A..N)`}] = (x, y) => - | ${binTuple("combine")} + | ): CommutativeSemigroup[${`(A..N)`}] = + | Semigroup.catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}] | implicit def catsKernelStdMonoidForTuple$arity[${`A..N`}]( | implicit ${constraints("Monoid")} - | ): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | ): Monoid[${`(A..N)`}] = + | Semigroup.catsKernelMonoidForTuple$arity[${`A..N`}] + |""" } ), InstanceDef( @@ -234,12 +220,12 @@ object KernelBoiler { block""" | implicit def catsKernelStdSemigroupForTuple$arity[${`A..N`}]( | implicit ${constraints("Semigroup")} - | ): Semigroup[${`(A..N)`}] = (x, y) => - | ${binTuple("combine")} + | ): Semigroup[${`(A..N)`}] = + | Semigroup.catsKernelSemigroupForTuple$arity[${`A..N`}] | implicit def catsKernelStdEqForTuple$arity[${`A..N`}]( | implicit ${constraints("Eq")} - | ): Eq[${`(A..N)`}] = (x, y) => - | ${binMethod("eqv").mkString(" && ")} + | ): Eq[${`(A..N)`}] = + | Eq.catsKernelEqForTuple$arity[${`A..N`}] |""" } ), @@ -252,9 +238,9 @@ object KernelBoiler { block""" | implicit def catsKernelBandForTuple$arity[${`A..N`}]( | implicit ${constraints("Band")} - | ): Band[${`(A..N)`}] = (x, y) => + | ): Band[${`(A..N)`}] = Band.instance { (x, y) => | ${binTuple("combine")} - |""" + | }""" } ), InstanceDef( @@ -266,10 +252,10 @@ object KernelBoiler { block""" | implicit def catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}]( | implicit ${constraints("BoundedSemilattice")} - | ): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | ): BoundedSemilattice[${`(A..N)`}] = BoundedSemilattice.instance( + | ${nullaryTuple("empty")}, + | (x, y) => ${binTuple("combine")} + | )""" } ), InstanceDef( @@ -281,11 +267,11 @@ object KernelBoiler { block""" | implicit def catsKernelCommutativeGroupForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeGroup")} - | ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | }""" + | ): CommutativeGroup[${`(A..N)`}] = CommutativeGroup.instance( + | ${nullaryTuple("empty")}, + | x => ${unaryTuple("inverse")}, + | (x, y) => ${binTuple("combine")} + | )""" } ), InstanceDef( @@ -297,10 +283,10 @@ object KernelBoiler { block""" | implicit def catsKernelCommutativeMonoidForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeMonoid")} - | ): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | ): CommutativeMonoid[${`(A..N)`}] = CommutativeMonoid.instance( + | ${nullaryTuple("empty")}, + | (x, y) => ${binTuple("combine")} + | )""" } ), InstanceDef( @@ -312,9 +298,9 @@ object KernelBoiler { block""" | implicit def catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeSemigroup")} - | ): CommutativeSemigroup[${`(A..N)`}] = (x, y) => + | ): CommutativeSemigroup[${`(A..N)`}] = CommutativeSemigroup.instance { (x, y) => | ${binTuple("combine")} - |""" + | }""" } ), InstanceDef( @@ -326,9 +312,9 @@ object KernelBoiler { block""" | implicit def catsKernelEqForTuple$arity[${`A..N`}]( | implicit ${constraints("Eq")} - | ): Eq[${`(A..N)`}] = (x, y) => + | ): Eq[${`(A..N)`}] = Eq.instance { (x, y) => | ${binMethod("eqv").mkString(" && ")} - |""" + | }""" } ), InstanceDef( @@ -340,11 +326,11 @@ object KernelBoiler { block""" | implicit def catsKernelGroupForTuple$arity[${`A..N`}]( | implicit ${constraints("Group")} - | ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")} - | }""" + | ): Group[${`(A..N)`}] = Group.instance( + | ${nullaryTuple("empty")}, + | x => ${unaryTuple("inverse")}, + | (x, y) => ${binTuple("combine")} + | )""" } ), InstanceDef( @@ -356,12 +342,10 @@ object KernelBoiler { block""" | implicit def catsKernelHashForTuple$arity[${`A..N`}]( | implicit ${constraints("Hash")} - | ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] { - | def hash(x: ${`(A..N)`}): Int = - | ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() - | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean = - | ${binMethod("eqv").mkString(" && ")} - | }""" + | ): Hash[${`(A..N)`}] = Hash.instance( + | x => ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode(), + | (x, y) => ${binMethod("eqv").mkString(" && ")} + | )""" } ), InstanceDef( @@ -373,10 +357,10 @@ object KernelBoiler { block""" | implicit def catsKernelMonoidForTuple$arity[${`A..N`}]( | implicit ${constraints("Monoid")} - | ): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] { - | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")} - | def empty: ${`(A..N)`} = ${nullaryTuple("empty")} - | }""" + | ): Monoid[${`(A..N)`}] = Monoid.instance( + | ${nullaryTuple("empty")}, + | (x, y) => ${binTuple("combine")} + | )""" } ), InstanceDef( @@ -388,9 +372,9 @@ object KernelBoiler { block""" | implicit def catsKernelOrderForTuple$arity[${`A..N`}]( | implicit ${constraints("Order")} - | ): Order[${`(A..N)`}] = (x, y) => + | ): Order[${`(A..N)`}] = Order.from { (x, y) => | ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0) - |""" + | }""" } ), InstanceDef( @@ -402,9 +386,9 @@ object KernelBoiler { block""" | implicit def catsKernelPartialOrderForTuple$arity[${`A..N`}]( | implicit ${constraints("PartialOrder")} - | ): PartialOrder[${`(A..N)`}] = (x, y) => + | ): PartialOrder[${`(A..N)`}] = PartialOrder.from { (x, y) => | ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0) - |""" + | }""" } ), InstanceDef( @@ -416,9 +400,9 @@ object KernelBoiler { block""" | implicit def catsKernelSemigroupForTuple$arity[${`A..N`}]( | implicit ${constraints("Semigroup")} - | ): Semigroup[${`(A..N)`}] = (x, y) => + | ): Semigroup[${`(A..N)`}] = Semigroup.instance { (x, y) => | ${binTuple("combine")} - |""" + | }""" } ), InstanceDef( @@ -430,9 +414,9 @@ object KernelBoiler { block""" | implicit def catsKernelSemilatticeForTuple$arity[${`A..N`}]( | implicit ${constraints("Semilattice")} - | ): Semilattice[${`(A..N)`}] = (x, y) => + | ): Semilattice[${`(A..N)`}] = Semilattice.instance { (x, y) => | ${binTuple("combine")} - |""" + | }""" } ) ) From da85e2e9539d19f1d955fcf12f527f0d8e6935e3 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 8 May 2021 22:11:17 +0200 Subject: [PATCH 3/8] Optimize cats-core boilerplate --- project/Boilerplate.scala | 16 ++--- project/TupleBifunctorInstancesBoiler.scala | 20 ++++--- project/TupleBitraverseInstancesBoiler.scala | 43 +++++++++----- project/TupleMonadInstancesBoiler.scala | 40 ++++++------- project/TupleShowInstancesBoiler.scala | 4 +- ...upleUnorderedFoldableInstancesBoiler.scala | 58 ++++++++++--------- 6 files changed, 95 insertions(+), 86 deletions(-) diff --git a/project/Boilerplate.scala b/project/Boilerplate.scala index 978c99ffaf..18d0f38224 100644 --- a/project/Boilerplate.scala +++ b/project/Boilerplate.scala @@ -74,10 +74,6 @@ object Boilerplate { if (arity <= 2) "(*, *)" else `A..(N - 2)`.mkString("(", ", ", ", *, *)") val `a..(n - 1)` = (0 until (arity - 1)).map(n => s"a$n") - val `fa._1..fa._(n - 2)` = - if (arity <= 2) "" else (0 until (arity - 2)).map(n => s"fa._${n + 1}").mkString("", ", ", ", ") - val `pure(fa._1..(n - 2))` = - if (arity <= 2) "" else (0 until (arity - 2)).map(n => s"G.pure(fa._${n + 1})").mkString("", ", ", ", ") val `a0, a(n - 1)` = if (arity <= 1) "" else `a..(n - 1)`.mkString(", ") val `[A0, A(N - 1)]` = if (arity <= 1) "" else `A..(N - 1)`.mkString("[", ", ", "]") val `(A0, A(N - 1))` = @@ -87,19 +83,15 @@ object Boilerplate { val `(A..N - 1, *)` = if (arity == 1) "Tuple1" else `A..(N - 1)`.mkString("(", ", ", ", *)") - val `(fa._1..(n - 1))` = - if (arity <= 1) "Tuple1.apply" else (0 until (arity - 1)).map(n => s"fa._${n + 1}").mkString("(", ", ", ", _)") def `A0, A(N - 1)&`(a: String): String = if (arity <= 1) s"Tuple1[$a]" else `A..(N - 1)`.mkString("(", ", ", s", $a)") - - def `fa._1..(n - 1) & `(a: String): String = - if (arity <= 1) s"Tuple1($a)" else (0 until (arity - 1)).map(n => s"fa._${n + 1}").mkString("(", ", ", s", $a)") - - def `constraints A..N`(c: String): String = synTypes.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")") + def `constraints A..N`(c: String): String = + synTypes.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")") def `constraints A..(N-1)`(c: String): String = if (arity <= 1) "" else `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")") - def `parameters A..(N-1)`(c: String): String = `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString(", ") + def `parameters A..(N-1)`(c: String): String = + `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString(", ") } trait Template { diff --git a/project/TupleBifunctorInstancesBoiler.scala b/project/TupleBifunctorInstancesBoiler.scala index e88baaf60a..b4e151ee98 100644 --- a/project/TupleBifunctorInstancesBoiler.scala +++ b/project/TupleBifunctorInstancesBoiler.scala @@ -5,7 +5,7 @@ import Boilerplate.{Template, TemplateVals} import sbt.File object GenTupleBifunctorInstances extends Template { - override def range = 1 to 11 + override def range = 2 to 11 override def filename(root: sbt.File): File = root / "cats" / "instances" / "NTupleBifunctorInstances.scala" @@ -18,15 +18,17 @@ object GenTupleBifunctorInstances extends Template { |package instances | |private[cats] trait NTupleBifunctorInstances { -${if (arity > 1) - block""" + | + | private def instance[F[_, _]](bim: (F[Any, Any], Any => Any, Any => Any) => F[Any, Any]): Bifunctor[F] = + | new Bifunctor[F] { + | def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D] = + | bim(fab.asInstanceOf[F[Any, Any]], f.asInstanceOf[Any => Any], g.asInstanceOf[Any => Any]).asInstanceOf[F[C, D]] + | } + - - implicit final def catsStdBifunctorForTuple$arity${`[A0, A(N - 2)]`}: Bifunctor[${`(A..N - 2, *, *)`}] = - - new Bifunctor[${`(A..N - 2, *, *)`}] { - - def bimap[A, B, C, D](fa: (${`A0, A(N - 2)`}A, B))(f: A => C, g: B => D): (${`A0, A(N - 2)`}C, D) = (${`fa._1..fa._(n - 2)`}f(fa._${arity - 1}), g(fa._$arity)) - - }""" - else - block""" - -"""} + - instance[${`(A..N - 2, *, *)`}] { (fab, f, g) => + - fab.copy(_${arity - 1} = f(fab._${arity - 1}), _$arity = g(fab._$arity)) + - } |}""" } } diff --git a/project/TupleBitraverseInstancesBoiler.scala b/project/TupleBitraverseInstancesBoiler.scala index 4933d44f07..5901b26cd1 100644 --- a/project/TupleBitraverseInstancesBoiler.scala +++ b/project/TupleBitraverseInstancesBoiler.scala @@ -5,7 +5,7 @@ import Boilerplate.{Template, TemplateVals} import sbt.File object GenTupleBitraverseInstances extends Template { - override def range = 1 to 11 + override def range = 2 to 11 override def filename(root: sbt.File): File = root / "cats" / "instances" / "NTupleBitraverseInstances.scala" @@ -18,20 +18,35 @@ object GenTupleBitraverseInstances extends Template { |package instances | |private[cats] trait NTupleBitraverseInstances { -${if (arity > 1) - block""" + | protected type γ[_] + | + | private def instance[F[_, _] <: Product]( + | bitrav: (F[Any, Any], Applicative[γ], Any => γ[Any], Any => γ[Any]) => γ[F[Any, Any]] + | ): Bitraverse[F] = new Bitraverse[F] { + | def bitraverse[G[_], A, B, C, D](fab: F[A, B])(f: A => G[C], g: B => G[D])(implicit G: Applicative[G]): G[F[C, D]] = + | bitrav( + | fab.asInstanceOf[F[Any, Any]], + | G.asInstanceOf[Applicative[γ]], + | f.asInstanceOf[Any => γ[Any]], + | g.asInstanceOf[Any => γ[Any]] + | ).asInstanceOf[G[F[C, D]]] + | + | @inline private def last1[A, B](fab: F[A, B]): A = + | fab.productElement(fab.productArity - 2).asInstanceOf[A] + | @inline private def last2[A, B](fab: F[A, B]): B = + | fab.productElement(fab.productArity - 1).asInstanceOf[B] + | def bifoldLeft[A, B, C](fab: F[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C = + | g(f(c, last1(fab)), last2(fab)) + | def bifoldRight[A, B, C](fab: F[A, B], c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] = + | g(last2(fab), f(last1(fab), c)) + | } + - - implicit final def catsStdBitraverseForTuple$arity${`[A0, A(N - 2)]`}: Bitraverse[${`(A..N - 2, *, *)`}] = - - new Bitraverse[${`(A..N - 2, *, *)`}] { - - def bitraverse[G[_], A, B, C, D](fa: (${`A0, A(N - 2)`}A, B))(f: A => G[C], g: B => G[D])(implicit G: Applicative[G]): G[(${`A0, A(N - 2)`}C, D)] = - - G.tuple$arity(${`pure(fa._1..(n - 2))`}f(fa._${arity - 1}), g(fa._$arity)) - - def bifoldLeft[A, B, C](fa: (${`A0, A(N - 2)`}A, B), c: C)(f: (C, A) => C, g: (C, B) => C): C = - - g(f(c, fa._${arity - 1}), fa._$arity) - - def bifoldRight[A, B, C](fa: (${`A0, A(N - 2)`}A, B), c: Eval[C])(f: (A, Eval[C]) => Eval[C], g: (B, Eval[C]) => Eval[C]): Eval[C] = - - g(fa._$arity, f(fa._${arity - 1}, c)) - - }""" - else - block""" - -"""} + - instance { (fab, G, f, g) => + - G.map2(f(fab._${arity - 1}), g(fab._$arity)) { (x, y) => + - fab.copy(_${arity - 1} = x, _$arity = y) + - } + - } |}""" } } diff --git a/project/TupleMonadInstancesBoiler.scala b/project/TupleMonadInstancesBoiler.scala index c38cb33449..cfc277b2d3 100644 --- a/project/TupleMonadInstancesBoiler.scala +++ b/project/TupleMonadInstancesBoiler.scala @@ -56,20 +56,21 @@ object GenTupleMonadInstances extends Template { |import scala.annotation.tailrec | |private[cats] trait NTupleMonadInstances extends NTupleMonadInstances1 { + | + | private def instance[F[_] <: Product](cofMap: (F[Any], F[Any] => Any) => F[Any]): Comonad[F] = + | new Comonad[F] { + | def coflatMap[A, B](fa: F[A])(f: F[A] => B) = + | cofMap(fa.asInstanceOf[F[Any]], f.asInstanceOf[F[Any] => Any]).asInstanceOf[F[B]] + | def extract[A](fa: F[A]) = + | fa.productElement(fa.productArity - 1).asInstanceOf[A] + | def map[A, B](fa: F[A])(f: A => B) = + | coflatMap(fa)(fa => f(extract(fa))) + | } + - - implicit final def catsStdInstancesForTuple$arity${`[A0, A(N - 1)]`}: Comonad[${`(A..N - 1, *)`}] = - - new Comonad[${`(A..N - 1, *)`}] { - - def coflatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: (${`A0, A(N - 1)&`("A")}) => B): ${`A0, A(N - 1)&`( - "B" - )} = ${`fa._1..(n - 1) & `( - "f(fa)" - )} - - def extract[A](fa: ${`A0, A(N - 1)&`("A")}): A = fa._$arity - - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} = - - ${`fa._1..(n - 1) & `(s"f(fa._$arity)")} - - override def coflatten[A](fa: ${`A0, A(N - 1)&`("A")}): $coflattenReturn = ${`fa._1..(n - 1) & `("fa")} - - } + - instance((fa, f) => fa.copy(_$arity = f(fa))) |} - |private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 { + |private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 { this: NTupleMonadInstances => - implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`( "CommutativeMonoid" )}: CommutativeMonad[${`(A..N - 1, *)`}] = @@ -77,28 +78,25 @@ object GenTupleMonadInstances extends Template { - def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod - } |} - |private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 { + |private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 { this: NTupleMonadInstances => - implicit final def catsStdCommutativeFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`( "CommutativeSemigroup" )}: CommutativeFlatMap[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeFlatMap[${`(A..N - 1, *)`}] |} - |private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 { + |private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 { this: NTupleMonadInstances => - implicit def catsStdMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`("Monoid")}: Monad[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with Monad[${`(A..N - 1, *)`}] { - def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod - } |} - |private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 { + |private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 { this: NTupleMonadInstances => - implicit def catsStdFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`("Semigroup")}: FlatMap[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) |} - |private[cats] sealed trait NTupleMonadInstances5 { + |private[cats] sealed trait NTupleMonadInstances5 { this: NTupleMonadInstances => - implicit def catsStdInvariantForTuple$arity${`[A0, A(N - 1)]`}: Invariant[${`(A..N - 1, *)`}] = - - new Invariant[${`(A..N - 1, *)`}] { - - def imap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: B => A): ${`A0, A(N - 1)&`("B")} = - - ${`fa._1..(n - 1) & `(s"f(fa._$arity)")} - - } + - catsStdInstancesForTuple$arity |} - -private[instances] class $flatMapTupleClass${`[A0, A(N - 1)]`}(${`parameters A..(N-1)`("Semigroup")}) extends FlatMap[${`(A..N - 1, *)`}] { @@ -107,7 +105,7 @@ object GenTupleMonadInstances extends Template { - override def product[A, B](fa: ${`A0, A(N - 1)&`("A")}, fb: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("(A, B)")} = - ${`combine A..(N - 1)`("fa", "fb", s"(fa._$arity, fb._$arity)")} - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} = - - ${`fa._1..(n - 1) & `(s"f(fa._$arity)")} + - fa.copy(_$arity = f(fa._$arity)) - def flatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("B")} = { ${if (arity > 1) block""" - val xb = f(fa._$arity) diff --git a/project/TupleShowInstancesBoiler.scala b/project/TupleShowInstancesBoiler.scala index f3273683d8..b1e4ae2b62 100644 --- a/project/TupleShowInstancesBoiler.scala +++ b/project/TupleShowInstancesBoiler.scala @@ -26,9 +26,7 @@ object GenTupleShowInstances extends Template { | |private[cats] trait NTupleShowInstances { - implicit final def catsStdShowForTuple$arity[${`A..N`}]${`constraints A..N`("Show")}: Show[${`(A..N)`}] = - - new Show[${`(A..N)`}] { - - def show(f: ${`(A..N)`}): String = $showMethod - - } + - f => $showMethod |}""" } } diff --git a/project/TupleUnorderedFoldableInstancesBoiler.scala b/project/TupleUnorderedFoldableInstancesBoiler.scala index cf9fbfe8d4..224e277f73 100644 --- a/project/TupleUnorderedFoldableInstancesBoiler.scala +++ b/project/TupleUnorderedFoldableInstancesBoiler.scala @@ -18,33 +18,37 @@ object GenTupleUnorderedFoldableInstances extends Template { |package instances | |private[cats] trait NTupleUnorderedFoldableInstances { -- implicit final def catsUnorderedFoldableInstancesForTuple$arity${`[A0, A(N - 1)]`}: Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] = -- new Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] { -- def traverse[G[_], A, B](fa: ${`A0, A(N - 1)&`( - "A" - )})(f: A => G[B])(implicit G: Applicative[G]): G[${`A0, A(N - 1)&`( - "B" - )}] = -- G.map(f(fa._$arity))(${`(fa._1..(n - 1))`}) -- def foldLeft[A, B](fa: ${`A0, A(N - 1)&`("A")}, b: B)(f: (B, A) => B): B = f(b, fa._$arity) -- def foldRight[A, B](fa: ${`A0, A(N - 1)&`("A")}, lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = f(fa._$arity, lb) -- override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} = -- ${`fa._1..(n - 1) & `(s"f(fa._$arity)")} -- override def foldMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(implicit B: Monoid[B]): B = f(fa._$arity) -- override def reduce[A](fa: ${`A0, A(N - 1)&`("A")})(implicit A: Semigroup[A]): A = fa._$arity -- def reduceLeftTo[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (B, A) => B): B = f(fa._$arity) -- override def reduceLeft[A](fa: ${`A0, A(N - 1)&`("A")})(f: (A, A) => A): A = fa._$arity -- override def reduceLeftToOption[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (B, A) => B): Option[B] = Some(f(fa._$arity)) -- override def reduceRight[A](fa: ${`A0, A(N - 1)&`("A")})(f: (A, Eval[A]) => Eval[A]): Eval[A] = Now(fa._$arity) -- def reduceRightTo[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = Now(f(fa._$arity)) -- override def reduceRightToOption[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] = Now(Some(f(fa._$arity))) -- override def reduceMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(implicit B: Semigroup[B]): B = f(fa._$arity) -- override def size[A](fa: ${`A0, A(N - 1)&`("A")}): Long = 1L -- override def get[A](fa: ${`A0, A(N - 1)&`("A")})(idx: Long): Option[A] = if (idx == 0L) Some(fa._$arity) else None -- override def exists[A](fa: ${`A0, A(N - 1)&`("A")})(p: A => Boolean): Boolean = p(fa._$arity) -- override def forall[A](fa: ${`A0, A(N - 1)&`("A")})(p: A => Boolean): Boolean = p(fa._$arity) -- override def isEmpty[A](fa: ${`A0, A(N - 1)&`("A")}): Boolean = false -- } + | protected type γ[_] + | + | private def instance[F[_] <: Product]( + | trav: (F[Any], Applicative[γ], Any => γ[Any]) => γ[F[Any]] + | ): Traverse[F] with Reducible[F] = + | new Traverse[F] with Reducible[F] { + | def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]) = + | trav(fa.asInstanceOf[F[Any]], G.asInstanceOf[Applicative[γ]], f.asInstanceOf[Any => γ[Any]]).asInstanceOf[G[F[B]]] + | @inline private def last[A](fa: F[A]): A = + | fa.productElement(fa.productArity - 1).asInstanceOf[A] + | def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = f(b, last(fa)) + | def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = f(last(fa), lb) + | override def foldMap[A, B](fa: F[A])(f: A => B)(implicit B: Monoid[B]): B = f(last(fa)) + | override def reduce[A](fa: F[A])(implicit A: Semigroup[A]): A = last(fa) + | def reduceLeftTo[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): B = f(last(fa)) + | override def reduceLeft[A](fa: F[A])(f: (A, A) => A): A = last(fa) + | override def reduceLeftToOption[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): Option[B] = Some(f(last(fa))) + | override def reduceRight[A](fa: F[A])(f: (A, Eval[A]) => Eval[A]): Eval[A] = Now(last(fa)) + | def reduceRightTo[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = Now(f(last(fa))) + | override def reduceRightToOption[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[Option[B]] = Now(Some(f(last(fa)))) + | override def reduceMap[A, B](fa: F[A])(f: A => B)(implicit B: Semigroup[B]): B = f(last(fa)) + | override def size[A](fa: F[A]): Long = 1L + | override def get[A](fa: F[A])(idx: Long): Option[A] = if (idx == 0L) Some(last(fa)) else None + | override def exists[A](fa: F[A])(p: A => Boolean): Boolean = p(last(fa)) + | override def forall[A](fa: F[A])(p: A => Boolean): Boolean = p(last(fa)) + | override def isEmpty[A](fa: F[A]): Boolean = false + | } + - + - implicit final def catsUnorderedFoldableInstancesForTuple$arity${`[A0, A(N - 1)]`} + - : Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] + - = instance((fa, G, f) => G.map(f(fa._$arity))(x => fa.copy(_$arity = x))) |}""" } } From 8ae7a40ad109e5aac57f2c6ee334b2436d173c66 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Thu, 26 Aug 2021 22:18:18 +0300 Subject: [PATCH 4/8] Optimize AlgebraBoilerplate by using instance constructors --- .../src/main/scala/algebra/ring/Rig.scala | 8 +++ .../src/main/scala/algebra/ring/Ring.scala | 9 +++ .../src/main/scala/algebra/ring/Rng.scala | 8 +++ .../main/scala/algebra/ring/Semiring.scala | 7 +++ project/AlgebraBoilerplate.scala | 60 +++++++++---------- 5 files changed, 61 insertions(+), 31 deletions(-) diff --git a/algebra-core/src/main/scala/algebra/ring/Rig.scala b/algebra-core/src/main/scala/algebra/ring/Rig.scala index 532866acaf..2ebdbe3df6 100644 --- a/algebra-core/src/main/scala/algebra/ring/Rig.scala +++ b/algebra-core/src/main/scala/algebra/ring/Rig.scala @@ -19,4 +19,12 @@ trait Rig[@sp(Int, Long, Float, Double) A] extends Any with Semiring[A] with Mul object Rig extends AdditiveMonoidFunctions[Rig] with MultiplicativeMonoidFunctions[Rig] { @inline final def apply[A](implicit ev: Rig[A]): Rig[A] = ev + + @inline private[algebra] def instance[A](z: A, o: A, add: (A, A) => A, mul: (A, A) => A): Rig[A] = + new Rig[A] { + val zero: A = z + val one: A = o + def plus(x: A, y: A): A = add(x, y) + def times(x: A, y: A): A = mul(x, y) + } } diff --git a/algebra-core/src/main/scala/algebra/ring/Ring.scala b/algebra-core/src/main/scala/algebra/ring/Ring.scala index 6606817046..b8bea4d7ea 100644 --- a/algebra-core/src/main/scala/algebra/ring/Ring.scala +++ b/algebra-core/src/main/scala/algebra/ring/Ring.scala @@ -115,4 +115,13 @@ trait RingFunctions[R[T] <: Ring[T]] extends AdditiveGroupFunctions[R] with Mult object Ring extends RingFunctions[Ring] { @inline final def apply[A](implicit ev: Ring[A]): Ring[A] = ev + + @inline private[algebra] def instance[A](z: A, o: A, neg: A => A, add: (A, A) => A, mul: (A, A) => A): Ring[A] = + new Ring[A] { + val zero: A = z + val one: A = o + def negate(x: A): A = neg(x) + def plus(x: A, y: A): A = add(x, y) + def times(x: A, y: A): A = mul(x, y) + } } diff --git a/algebra-core/src/main/scala/algebra/ring/Rng.scala b/algebra-core/src/main/scala/algebra/ring/Rng.scala index 94585327b5..afeb0e8b0c 100644 --- a/algebra-core/src/main/scala/algebra/ring/Rng.scala +++ b/algebra-core/src/main/scala/algebra/ring/Rng.scala @@ -19,4 +19,12 @@ trait Rng[@sp(Int, Long, Float, Double) A] extends Any with Semiring[A] with Add object Rng extends AdditiveGroupFunctions[Rng] with MultiplicativeSemigroupFunctions[Rng] { @inline final def apply[A](implicit ev: Rng[A]): Rng[A] = ev + + @inline private[algebra] def instance[A](z: A, neg: A => A, add: (A, A) => A, mul: (A, A) => A): Rng[A] = + new Rng[A] { + val zero: A = z + def negate(x: A): A = neg(x) + def plus(x: A, y: A): A = add(x, y) + def times(x: A, y: A): A = mul(x, y) + } } diff --git a/algebra-core/src/main/scala/algebra/ring/Semiring.scala b/algebra-core/src/main/scala/algebra/ring/Semiring.scala index ef9ca42420..1cb946e015 100644 --- a/algebra-core/src/main/scala/algebra/ring/Semiring.scala +++ b/algebra-core/src/main/scala/algebra/ring/Semiring.scala @@ -23,4 +23,11 @@ trait Semiring[@sp(Int, Long, Float, Double) A] object Semiring extends AdditiveMonoidFunctions[Semiring] with MultiplicativeSemigroupFunctions[Semiring] { @inline final def apply[A](implicit ev: Semiring[A]): Semiring[A] = ev + + @inline private[algebra] def instance[A](z: A, add: (A, A) => A, mul: (A, A) => A): Semiring[A] = + new Semiring[A] { + val zero: A = z + def plus(x: A, y: A): A = add(x, y) + def times(x: A, y: A): A = mul(x, y) + } } diff --git a/project/AlgebraBoilerplate.scala b/project/AlgebraBoilerplate.scala index cac6c3f7ee..5830ab0be6 100644 --- a/project/AlgebraBoilerplate.scala +++ b/project/AlgebraBoilerplate.scala @@ -44,9 +44,7 @@ object AlgebraBoilerplate { val synVals = (0 until arity).map(n => s"a$n") val `A..N` = synTypes.mkString(", ") val `a..n` = synVals.mkString(", ") - val `_.._` = Seq.fill(arity)("_").mkString(", ") val `(A..N)` = if (arity == 1) "Tuple1[A0]" else synTypes.mkString("(", ", ", ")") - val `(_.._)` = if (arity == 1) "Tuple1[_]" else Seq.fill(arity)("_").mkString("(", ", ", ")") val `(a..n)` = if (arity == 1) "Tuple1(a)" else synVals.mkString("(", ", ", ")") } @@ -86,32 +84,32 @@ object AlgebraBoilerplate { import tv._ def constraints(constraint: String) = - synTypes.map(tpe => s"${tpe}: ${constraint}[${tpe}]").mkString(", ") + synTypes.map(tpe => s"$tpe: $constraint[$tpe]").mkString(", ") def tuple(results: TraversableOnce[String]) = { val resultsVec = results.toVector val a = synTypes.size val r = s"${0.until(a).map(i => resultsVec(i)).mkString(", ")}" if (a == 1) "Tuple1(" ++ r ++ ")" - else s"(${r})" + else s"($r)" } def binMethod(name: String) = synTypes.zipWithIndex.iterator.map { case (tpe, i) => val j = i + 1 - s"${tpe}.${name}(x._${j}, y._${j})" + s"$tpe.$name(x._$j, y._$j)" } def binTuple(name: String) = tuple(binMethod(name)) def unaryTuple(name: String) = { - val m = synTypes.zipWithIndex.map { case (tpe, i) => s"${tpe}.${name}(x._${i + 1})" } + val m = synTypes.zipWithIndex.map { case (tpe, i) => s"$tpe.$name(x._${i + 1})" } tuple(m) } def nullaryTuple(name: String) = { - val m = synTypes.map(tpe => s"${tpe}.${name}") + val m = synTypes.map(tpe => s"$tpe.$name") tuple(m) } @@ -124,36 +122,36 @@ object AlgebraBoilerplate { |trait TupleInstances extends cats.kernel.instances.TupleInstances { - - implicit def tuple${arity}Rig[${`A..N`}](implicit ${constraints("Rig")}): Rig[${`(A..N)`}] = - - new Rig[${`(A..N)`}] { - - def one: ${`(A..N)`} = ${nullaryTuple("one")} - - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")} - - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")} - - def zero: ${`(A..N)`} = ${nullaryTuple("zero")} - - } + - Rig.instance( + - ${nullaryTuple("zero")}, + - ${nullaryTuple("one")}, + - (x, y) => ${binTuple("plus")}, + - (x, y) => ${binTuple("times")} + - ) - - implicit def tuple${arity}Ring[${`A..N`}](implicit ${constraints("Ring")}): Ring[${`(A..N)`}] = - - new Ring[${`(A..N)`}] { - - def one: ${`(A..N)`} = ${nullaryTuple("one")} - - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")} - - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")} - - def zero: ${`(A..N)`} = ${nullaryTuple("zero")} - - def negate(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("negate")} - - } + - Ring.instance( + - ${nullaryTuple("zero")}, + - ${nullaryTuple("one")}, + - x => ${unaryTuple("negate")}, + - (x, y) => ${binTuple("plus")}, + - (x, y) => ${binTuple("times")} + - ) - - implicit def tuple${arity}Rng[${`A..N`}](implicit ${constraints("Rng")}): Rng[${`(A..N)`}] = - - new Rng[${`(A..N)`}] { - - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")} - - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")} - - def zero: ${`(A..N)`} = ${nullaryTuple("zero")} - - def negate(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("negate")} - - } + - Rng.instance( + - ${nullaryTuple("zero")}, + - x => ${unaryTuple("negate")}, + - (x, y) => ${binTuple("plus")}, + - (x, y) => ${binTuple("times")} + - ) - - implicit def tuple${arity}Semiring[${`A..N`}](implicit ${constraints("Semiring")}): Semiring[${`(A..N)`}] = - - new Semiring[${`(A..N)`}] { - - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("plus")} - - def times(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("times")} - - def zero: ${`(A..N)`} = ${nullaryTuple("zero")} - - } + - Semiring.instance( + - ${nullaryTuple("zero")}, + - (x, y) => ${binTuple("plus")}, + - (x, y) => ${binTuple("times")} + - ) |} """ } From f24bb2d4a9e1c2c9a5d9532765b992a696642567 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Thu, 10 Feb 2022 08:47:11 +0100 Subject: [PATCH 5/8] Restore AlgebraBoilerplate to classes --- .../src/main/scala/algebra/ring/Rig.scala | 8 ---- .../src/main/scala/algebra/ring/Ring.scala | 9 ---- .../src/main/scala/algebra/ring/Rng.scala | 8 ---- .../main/scala/algebra/ring/Semiring.scala | 7 --- project/AlgebraBoilerplate.scala | 48 +++++++++---------- 5 files changed, 24 insertions(+), 56 deletions(-) diff --git a/algebra-core/src/main/scala/algebra/ring/Rig.scala b/algebra-core/src/main/scala/algebra/ring/Rig.scala index 2ebdbe3df6..532866acaf 100644 --- a/algebra-core/src/main/scala/algebra/ring/Rig.scala +++ b/algebra-core/src/main/scala/algebra/ring/Rig.scala @@ -19,12 +19,4 @@ trait Rig[@sp(Int, Long, Float, Double) A] extends Any with Semiring[A] with Mul object Rig extends AdditiveMonoidFunctions[Rig] with MultiplicativeMonoidFunctions[Rig] { @inline final def apply[A](implicit ev: Rig[A]): Rig[A] = ev - - @inline private[algebra] def instance[A](z: A, o: A, add: (A, A) => A, mul: (A, A) => A): Rig[A] = - new Rig[A] { - val zero: A = z - val one: A = o - def plus(x: A, y: A): A = add(x, y) - def times(x: A, y: A): A = mul(x, y) - } } diff --git a/algebra-core/src/main/scala/algebra/ring/Ring.scala b/algebra-core/src/main/scala/algebra/ring/Ring.scala index b8bea4d7ea..6606817046 100644 --- a/algebra-core/src/main/scala/algebra/ring/Ring.scala +++ b/algebra-core/src/main/scala/algebra/ring/Ring.scala @@ -115,13 +115,4 @@ trait RingFunctions[R[T] <: Ring[T]] extends AdditiveGroupFunctions[R] with Mult object Ring extends RingFunctions[Ring] { @inline final def apply[A](implicit ev: Ring[A]): Ring[A] = ev - - @inline private[algebra] def instance[A](z: A, o: A, neg: A => A, add: (A, A) => A, mul: (A, A) => A): Ring[A] = - new Ring[A] { - val zero: A = z - val one: A = o - def negate(x: A): A = neg(x) - def plus(x: A, y: A): A = add(x, y) - def times(x: A, y: A): A = mul(x, y) - } } diff --git a/algebra-core/src/main/scala/algebra/ring/Rng.scala b/algebra-core/src/main/scala/algebra/ring/Rng.scala index afeb0e8b0c..94585327b5 100644 --- a/algebra-core/src/main/scala/algebra/ring/Rng.scala +++ b/algebra-core/src/main/scala/algebra/ring/Rng.scala @@ -19,12 +19,4 @@ trait Rng[@sp(Int, Long, Float, Double) A] extends Any with Semiring[A] with Add object Rng extends AdditiveGroupFunctions[Rng] with MultiplicativeSemigroupFunctions[Rng] { @inline final def apply[A](implicit ev: Rng[A]): Rng[A] = ev - - @inline private[algebra] def instance[A](z: A, neg: A => A, add: (A, A) => A, mul: (A, A) => A): Rng[A] = - new Rng[A] { - val zero: A = z - def negate(x: A): A = neg(x) - def plus(x: A, y: A): A = add(x, y) - def times(x: A, y: A): A = mul(x, y) - } } diff --git a/algebra-core/src/main/scala/algebra/ring/Semiring.scala b/algebra-core/src/main/scala/algebra/ring/Semiring.scala index 1cb946e015..ef9ca42420 100644 --- a/algebra-core/src/main/scala/algebra/ring/Semiring.scala +++ b/algebra-core/src/main/scala/algebra/ring/Semiring.scala @@ -23,11 +23,4 @@ trait Semiring[@sp(Int, Long, Float, Double) A] object Semiring extends AdditiveMonoidFunctions[Semiring] with MultiplicativeSemigroupFunctions[Semiring] { @inline final def apply[A](implicit ev: Semiring[A]): Semiring[A] = ev - - @inline private[algebra] def instance[A](z: A, add: (A, A) => A, mul: (A, A) => A): Semiring[A] = - new Semiring[A] { - val zero: A = z - def plus(x: A, y: A): A = add(x, y) - def times(x: A, y: A): A = mul(x, y) - } } diff --git a/project/AlgebraBoilerplate.scala b/project/AlgebraBoilerplate.scala index 5830ab0be6..6f5b0528ec 100644 --- a/project/AlgebraBoilerplate.scala +++ b/project/AlgebraBoilerplate.scala @@ -122,36 +122,36 @@ object AlgebraBoilerplate { |trait TupleInstances extends cats.kernel.instances.TupleInstances { - - implicit def tuple${arity}Rig[${`A..N`}](implicit ${constraints("Rig")}): Rig[${`(A..N)`}] = - - Rig.instance( - - ${nullaryTuple("zero")}, - - ${nullaryTuple("one")}, - - (x, y) => ${binTuple("plus")}, - - (x, y) => ${binTuple("times")} - - ) + - new Rig[${`(A..N)`}] { + - def zero = ${nullaryTuple("zero")} + - def one = ${nullaryTuple("one")} + - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")} + - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")} + - } - - implicit def tuple${arity}Ring[${`A..N`}](implicit ${constraints("Ring")}): Ring[${`(A..N)`}] = - - Ring.instance( - - ${nullaryTuple("zero")}, - - ${nullaryTuple("one")}, - - x => ${unaryTuple("negate")}, - - (x, y) => ${binTuple("plus")}, - - (x, y) => ${binTuple("times")} - - ) + - new Ring[${`(A..N)`}] { + - def zero = ${nullaryTuple("zero")} + - def one = ${nullaryTuple("one")} + - def negate(x: ${`(A..N)`}) = ${unaryTuple("negate")} + - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")} + - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")} + - } - - implicit def tuple${arity}Rng[${`A..N`}](implicit ${constraints("Rng")}): Rng[${`(A..N)`}] = - - Rng.instance( - - ${nullaryTuple("zero")}, - - x => ${unaryTuple("negate")}, - - (x, y) => ${binTuple("plus")}, - - (x, y) => ${binTuple("times")} - - ) + - new Rng[${`(A..N)`}] { + - def zero = ${nullaryTuple("zero")} + - def negate(x: ${`(A..N)`}) = ${unaryTuple("negate")} + - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")} + - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")} + - } - - implicit def tuple${arity}Semiring[${`A..N`}](implicit ${constraints("Semiring")}): Semiring[${`(A..N)`}] = - - Semiring.instance( - - ${nullaryTuple("zero")}, - - (x, y) => ${binTuple("plus")}, - - (x, y) => ${binTuple("times")} - - ) + - new Semiring[${`(A..N)`}] { + - def zero = ${nullaryTuple("zero")} + - def plus(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("plus")} + - def times(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("times")} + - } |} """ } From 1185c8bf7954689328c21ae1b0692cb8160319bc Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Thu, 10 Feb 2022 08:52:26 +0100 Subject: [PATCH 6/8] Use Show.show --- core/src/main/scala/cats/Show.scala | 10 ++-------- project/TupleShowInstancesBoiler.scala | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala/cats/Show.scala b/core/src/main/scala/cats/Show.scala index de7b208a71..debed089a3 100644 --- a/core/src/main/scala/cats/Show.scala +++ b/core/src/main/scala/cats/Show.scala @@ -42,18 +42,12 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances { /** * creates an instance of [[Show]] using the provided function */ - def show[A](f: A => String): Show[A] = - new Show[A] { - def show(a: A): String = f(a) - } + def show[A](f: A => String): Show[A] = f(_) /** * creates an instance of [[Show]] using object toString */ - def fromToString[A]: Show[A] = - new Show[A] { - def show(a: A): String = a.toString - } + def fromToString[A]: Show[A] = _.toString final case class Shown(override val toString: String) extends AnyVal object Shown { diff --git a/project/TupleShowInstancesBoiler.scala b/project/TupleShowInstancesBoiler.scala index b1e4ae2b62..d590d26e3c 100644 --- a/project/TupleShowInstancesBoiler.scala +++ b/project/TupleShowInstancesBoiler.scala @@ -26,7 +26,7 @@ object GenTupleShowInstances extends Template { | |private[cats] trait NTupleShowInstances { - implicit final def catsStdShowForTuple$arity[${`A..N`}]${`constraints A..N`("Show")}: Show[${`(A..N)`}] = - - f => $showMethod + - Show.show(f => $showMethod) |}""" } } From 760015396ab166d006fd5e0a2c835936f8b9fbff Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Thu, 10 Feb 2022 09:42:51 +0100 Subject: [PATCH 7/8] Simplify GenTupleMonadInstances --- project/TupleMonadInstancesBoiler.scala | 132 +++++++++++------------- 1 file changed, 58 insertions(+), 74 deletions(-) diff --git a/project/TupleMonadInstancesBoiler.scala b/project/TupleMonadInstancesBoiler.scala index 23fd516581..46f66d7440 100644 --- a/project/TupleMonadInstancesBoiler.scala +++ b/project/TupleMonadInstancesBoiler.scala @@ -12,6 +12,9 @@ object GenTupleMonadInstances extends Template { override def content(tv: TemplateVals): String = { import tv._ + val `b..(n - 1)` = for (n <- 0 until arity - 1) yield s"b$n" + val `b:A..(n - 1):(N - 1)` = (for ((v, t) <- `b..(n - 1)`.zip(`A..(N - 1)`)) yield s"$v: $t").mkString(", ") + /** * This special case for N = 2 is needed because * of the deprecated versions in TupleInstances. @@ -21,31 +24,51 @@ object GenTupleMonadInstances extends Template { val flatMapTupleClass = if (arity == 2) "FlatMapNTuple2" else s"FlatMapTuple$arity" def `combine A..(N - 1)`(a: String, b: String, last: String): String = - if (arity <= 1) s"Tuple1($last)" + if (arity <= 1) + s"Tuple1($last)" else - `A..(N - 1)`.zipWithIndex.iterator - .map { case (an, i) => - s"$an.combine($a._${i + 1}, $b._${i + 1})" - } + `A..(N - 1)`.iterator.zipWithIndex + .map { case (an, i) => s"$an.combine($a._${i + 1}, $b._${i + 1})" } .mkString("(", ", ", s", $last)") - val coflattenReturn = - if (arity <= 1) "Tuple1[Tuple1[A]]" - else - s"${`A0, A(N - 1)&`(`A0, A(N - 1)&`("A"))}" - val monadPureMethod: String = if (arity <= 1) "Tuple1(a)" else `A..(N - 1)`.map(n => s"$n.empty").mkString("(", ", ", ", a)") val tailRecMCombine = - if (arity == 2) s"A0.combine(x, a0)" + `A..(N - 1)`.iterator.zipWithIndex + .map { case (an, i) => s"$an.combine(b$i, a$i)" } + .mkString(", ") + + val tailRecMMethod = + if (arity == 1) + block""" + - @tailrec + - def loop(a: A): Tuple1[B] = + - f(a) match { + - case Tuple1(Right(b)) => Tuple1(b) + - case Tuple1(Left(nextA)) => loop(nextA) + - } + - loop(a) + """ else - `A..(N - 1)`.zipWithIndex.iterator - .map { case (an, i) => - s"$an.combine(x._${i + 1}, a$i)" - } - .mkString(", ") + block""" + - @tailrec + - def loop(${`b:A..(n - 1):(N - 1)`}, a: A): ${`A0, A(N - 1)&`("B")} = + - f(a) match { + - case (${`a0, a(n - 1)`}, Right(b)) => ($tailRecMCombine, b) + - case (${`a0, a(n - 1)`}, Left(nextA)) => loop($tailRecMCombine, nextA) + - } + - f(a) match { + - case (${`a0, a(n - 1)`}, Right(b)) => (${`a0, a(n - 1)`}, b) + - case (${`a0, a(n - 1)`}, Left(nextA)) => loop(${`a0, a(n - 1)`}, nextA) + - } + """ + + val `:CommutativeMonoid` = `constraints A..(N-1)`("CommutativeMonoid") + val `:CommutativeSemigroup` = `constraints A..(N-1)`("CommutativeSemigroup") + val `:Monoid` = `constraints A..(N-1)`("Monoid") + val `:Semigroup` = `constraints A..(N-1)`("Semigroup") block""" | @@ -71,31 +94,23 @@ object GenTupleMonadInstances extends Template { - instance((fa, f) => fa.copy(_$arity = f(fa))) |} |private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 { this: NTupleMonadInstances => - - implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`( - "CommutativeMonoid" - )}: CommutativeMonad[${`(A..N - 1, *)`}] = + - implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`:CommutativeMonoid`}: CommutativeMonad[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeMonad[${`(A..N - 1, *)`}] { - - def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod + - def pure[A](a: A) = $monadPureMethod - } |} |private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 { this: NTupleMonadInstances => - - implicit final def catsStdCommutativeFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`( - "CommutativeSemigroup" - )}: CommutativeFlatMap[${`(A..N - 1, *)`}] = + - implicit final def catsStdCommutativeFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`:CommutativeSemigroup`}: CommutativeFlatMap[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeFlatMap[${`(A..N - 1, *)`}] |} |private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 { this: NTupleMonadInstances => - - implicit def catsStdMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`( - "Monoid" - )}: Monad[${`(A..N - 1, *)`}] = + - implicit def catsStdMonadForTuple$arity${`[A0, A(N - 1)]`}${`:Monoid`}: Monad[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with Monad[${`(A..N - 1, *)`}] { - - def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod + - def pure[A](a: A) = $monadPureMethod - } |} |private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 { this: NTupleMonadInstances => - - implicit def catsStdFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`( - "Semigroup" - )}: FlatMap[${`(A..N - 1, *)`}] = + - implicit def catsStdFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`:Semigroup`}: FlatMap[${`(A..N - 1, *)`}] = - new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) |} |private[cats] sealed trait NTupleMonadInstances5 { this: NTupleMonadInstances => @@ -103,59 +118,28 @@ object GenTupleMonadInstances extends Template { - catsStdInstancesForTuple$arity |} - - -private[instances] class $flatMapTupleClass${`[A0, A(N - 1)]`}(${`parameters A..(N-1)`( - "Semigroup" - )}) extends FlatMap[${`(A..N - 1, *)`}] { - - override def ap[A, B](ff: ${`A0, A(N - 1)&`("A => B")})(fa: ${`A0, A(N - 1)&`("A")}): ${`A0, A(N - 1)&`("B")} = + -private[instances] class $flatMapTupleClass${`[A0, A(N - 1)]`}(${`parameters A..(N-1)`("Semigroup")}) + - extends FlatMap[${`(A..N - 1, *)`}] { + - override def ap[A, B](ff: ${`A0, A(N - 1)&`("A => B")})(fa: ${`A0, A(N - 1)&`("A")}) = - ${`combine A..(N - 1)`("ff", "fa", s"ff._$arity(fa._$arity)")} - - override def product[A, B](fa: ${`A0, A(N - 1)&`("A")}, fb: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`( - "(A, B)" - )} = + - override def product[A, B](fa: ${`A0, A(N - 1)&`("A")}, fb: ${`A0, A(N - 1)&`("B")}) = - ${`combine A..(N - 1)`("fa", "fb", s"(fa._$arity, fb._$arity)")} - - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} = + - override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B) = - fa.copy(_$arity = f(fa._$arity)) - - def flatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("B")} = { - ${if (arity > 1) block""" - - val xb = f(fa._$arity) - - ${`combine A..(N - 1)`("fa", "xb", s"xb._$arity")} - """ - else block""" - - f(fa._1) - """} + - def flatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}) = { + - val xb = f(fa._$arity) + - ${`combine A..(N - 1)`("fa", "xb", s"xb._$arity")} - } - - override def productR[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("B")} = + - override def productR[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}) = - ${`combine A..(N - 1)`("a", "b", s"b._$arity")} - - override def productL[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("A")} = + - override def productL[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("B")}) = - ${`combine A..(N - 1)`("a", "b", s"a._$arity")} - - override def mproduct[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`( - "(A, B)" - )} = { + - override def mproduct[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}) = { - val xb = f(fa._$arity) - ${`combine A..(N - 1)`("fa", "xb", s"(fa._$arity, xb._$arity)")} - } - - def tailRecM[A, B](a: A)(f: A => ${`A0, A(N - 1)&`("Either[A, B]")}): ${`A0, A(N - 1)&`("B")} = { - - @tailrec -${if (arity > 1) block""" - - def loop(x: ${`(A0, A(N - 1))`}, aa: A): ${`A0, A(N - 1)&`("B")} = - - f(aa) match { - - case (${`a0, a(n - 1)`}, Right(b)) => ($tailRecMCombine, b) - - case (${`a0, a(n - 1)`}, Left(nextA)) => loop(($tailRecMCombine), nextA) - - } - - f(a) match { - - case (${`a0, a(n - 1)`}, Right(b)) => (${`a0, a(n - 1)`}, b) - - case (${`a0, a(n - 1)`}, Left(nextA)) => loop((${`a0, a(n - 1)`}), nextA) -""" - else block""" - - def loop(aa: A): Tuple1[B] = - - f(aa) match { - - case Tuple1(Right(b)) => Tuple1(b) - - case Tuple1(Left(nextA)) => loop(nextA) - - } - - f(a) match { - - case Tuple1(Right(b)) => Tuple1(b) - - case Tuple1(Left(nextA)) => loop(nextA) - """} - - } + - def tailRecM[A, B](a: A)(f: A => ${`A0, A(N - 1)&`("Either[A, B]")}) = { + - $tailRecMMethod - } -}""" } From 6ba7e4b782c0355c7fa2b5a787355a19b22d469a Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Thu, 10 Feb 2022 09:54:48 +0100 Subject: [PATCH 8/8] Convert back multi-method type class instances to anonymous classes --- .../scala/cats/kernel/CommutativeGroup.scala | 10 ------- kernel/src/main/scala/cats/kernel/Group.scala | 10 ------- kernel/src/main/scala/cats/kernel/Hash.scala | 9 ------ project/KernelBoiler.scala | 30 ++++++++++--------- 4 files changed, 16 insertions(+), 43 deletions(-) diff --git a/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala b/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala index b83cffdade..441ee2fcf1 100644 --- a/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala +++ b/kernel/src/main/scala/cats/kernel/CommutativeGroup.scala @@ -14,14 +14,4 @@ object CommutativeGroup extends GroupFunctions[CommutativeGroup] { * Access an implicit `CommutativeGroup[A]`. */ @inline final def apply[A](implicit ev: CommutativeGroup[A]): CommutativeGroup[A] = ev - - /** - * Create a `CommutativeGroup` instance from the given inverse and combine functions and empty value. - */ - @inline def instance[A](emp: A, inv: A => A, cmb: (A, A) => A): CommutativeGroup[A] = - new CommutativeGroup[A] { - val empty = emp - def inverse(a: A) = inv(a) - def combine(x: A, y: A) = cmb(x, y) - } } diff --git a/kernel/src/main/scala/cats/kernel/Group.scala b/kernel/src/main/scala/cats/kernel/Group.scala index d6bd693d43..785263bce7 100644 --- a/kernel/src/main/scala/cats/kernel/Group.scala +++ b/kernel/src/main/scala/cats/kernel/Group.scala @@ -74,14 +74,4 @@ object Group extends GroupFunctions[Group] { * Access an implicit `Group[A]`. */ @inline final def apply[A](implicit ev: Group[A]): Group[A] = ev - - /** - * Create a `Group` instance from the given inverse and combine functions and empty value. - */ - @inline def instance[A](emp: A, inv: A => A, cmb: (A, A) => A): Group[A] = - new Group[A] { - val empty = emp - def inverse(a: A) = inv(a) - def combine(x: A, y: A) = cmb(x, y) - } } diff --git a/kernel/src/main/scala/cats/kernel/Hash.scala b/kernel/src/main/scala/cats/kernel/Hash.scala index fe8f4f2a32..60ca354a08 100644 --- a/kernel/src/main/scala/cats/kernel/Hash.scala +++ b/kernel/src/main/scala/cats/kernel/Hash.scala @@ -53,15 +53,6 @@ object Hash extends HashFunctions[Hash] { def hash(x: A) = x.hashCode() def eqv(x: A, y: A) = x == y } - - /** - * Create a `Hash` instance from the given hash and equality functions. - */ - @inline def instance[A](h: A => Int, e: (A, A) => Boolean): Hash[A] = - new Hash[A] { - def hash(x: A) = h(x) - def eqv(x: A, y: A) = e(x, y) - } } trait HashToHashingConversion { diff --git a/project/KernelBoiler.scala b/project/KernelBoiler.scala index ee11019fa4..c12e42483e 100644 --- a/project/KernelBoiler.scala +++ b/project/KernelBoiler.scala @@ -267,11 +267,11 @@ object KernelBoiler { block""" | implicit def catsKernelCommutativeGroupForTuple$arity[${`A..N`}]( | implicit ${constraints("CommutativeGroup")} - | ): CommutativeGroup[${`(A..N)`}] = CommutativeGroup.instance( - | ${nullaryTuple("empty")}, - | x => ${unaryTuple("inverse")}, - | (x, y) => ${binTuple("combine")} - | )""" + | ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] { + | def empty = ${nullaryTuple("empty")} + | def inverse(x: ${`(A..N)`}) = ${unaryTuple("inverse")} + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("combine")} + | }""" } ), InstanceDef( @@ -326,11 +326,11 @@ object KernelBoiler { block""" | implicit def catsKernelGroupForTuple$arity[${`A..N`}]( | implicit ${constraints("Group")} - | ): Group[${`(A..N)`}] = Group.instance( - | ${nullaryTuple("empty")}, - | x => ${unaryTuple("inverse")}, - | (x, y) => ${binTuple("combine")} - | )""" + | ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] { + | def empty = ${nullaryTuple("empty")} + | def inverse(x: ${`(A..N)`}) = ${unaryTuple("inverse")} + | def combine(x: ${`(A..N)`}, y: ${`(A..N)`}) = ${binTuple("combine")} + | }""" } ), InstanceDef( @@ -342,10 +342,12 @@ object KernelBoiler { block""" | implicit def catsKernelHashForTuple$arity[${`A..N`}]( | implicit ${constraints("Hash")} - | ): Hash[${`(A..N)`}] = Hash.instance( - | x => ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode(), - | (x, y) => ${binMethod("eqv").mkString(" && ")} - | )""" + | ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] { + | def hash(x: ${`(A..N)`}) = + | ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode() + | def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}) = + | ${binMethod("eqv").mkString(" && ")} + | }""" } ), InstanceDef(