Skip to content

Commit 5f4a965

Browse files
committed
Optimize cats-core boilerplate
1 parent 1ae7ae0 commit 5f4a965

6 files changed

+95
-86
lines changed

project/Boilerplate.scala

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ object Boilerplate {
7474
if (arity <= 2) "(*, *)"
7575
else `A..(N - 2)`.mkString("(", ", ", ", *, *)")
7676
val `a..(n - 1)` = (0 until (arity - 1)).map(n => s"a$n")
77-
val `fa._1..fa._(n - 2)` =
78-
if (arity <= 2) "" else (0 until (arity - 2)).map(n => s"fa._${n + 1}").mkString("", ", ", ", ")
79-
val `pure(fa._1..(n - 2))` =
80-
if (arity <= 2) "" else (0 until (arity - 2)).map(n => s"G.pure(fa._${n + 1})").mkString("", ", ", ", ")
8177
val `a0, a(n - 1)` = if (arity <= 1) "" else `a..(n - 1)`.mkString(", ")
8278
val `[A0, A(N - 1)]` = if (arity <= 1) "" else `A..(N - 1)`.mkString("[", ", ", "]")
8379
val `(A0, A(N - 1))` =
@@ -87,19 +83,15 @@ object Boilerplate {
8783
val `(A..N - 1, *)` =
8884
if (arity == 1) "Tuple1"
8985
else `A..(N - 1)`.mkString("(", ", ", ", *)")
90-
val `(fa._1..(n - 1))` =
91-
if (arity <= 1) "Tuple1.apply" else (0 until (arity - 1)).map(n => s"fa._${n + 1}").mkString("(", ", ", ", _)")
9286

9387
def `A0, A(N - 1)&`(a: String): String =
9488
if (arity <= 1) s"Tuple1[$a]" else `A..(N - 1)`.mkString("(", ", ", s", $a)")
95-
96-
def `fa._1..(n - 1) & `(a: String): String =
97-
if (arity <= 1) s"Tuple1($a)" else (0 until (arity - 1)).map(n => s"fa._${n + 1}").mkString("(", ", ", s", $a)")
98-
99-
def `constraints A..N`(c: String): String = synTypes.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")")
89+
def `constraints A..N`(c: String): String =
90+
synTypes.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")")
10091
def `constraints A..(N-1)`(c: String): String =
10192
if (arity <= 1) "" else `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString("(implicit ", ", ", ")")
102-
def `parameters A..(N-1)`(c: String): String = `A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString(", ")
93+
def `parameters A..(N-1)`(c: String): String =
94+
`A..(N - 1)`.map(tpe => s"$tpe: $c[$tpe]").mkString(", ")
10395
}
10496

10597
trait Template {

project/TupleBifunctorInstancesBoiler.scala

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Boilerplate.{Template, TemplateVals}
55
import sbt.File
66

77
object GenTupleBifunctorInstances extends Template {
8-
override def range = 1 to 11
8+
override def range = 2 to 11
99
override def filename(root: sbt.File): File =
1010
root / "cats" / "instances" / "NTupleBifunctorInstances.scala"
1111

@@ -18,15 +18,17 @@ object GenTupleBifunctorInstances extends Template {
1818
|package instances
1919
|
2020
|private[cats] trait NTupleBifunctorInstances {
21-
${if (arity > 1)
22-
block"""
21+
|
22+
| private def instance[F[_, _]](bim: (F[Any, Any], Any => Any, Any => Any) => F[Any, Any]): Bifunctor[F] =
23+
| new Bifunctor[F] {
24+
| def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D] =
25+
| bim(fab.asInstanceOf[F[Any, Any]], f.asInstanceOf[Any => Any], g.asInstanceOf[Any => Any]).asInstanceOf[F[C, D]]
26+
| }
27+
-
2328
- implicit final def catsStdBifunctorForTuple$arity${`[A0, A(N - 2)]`}: Bifunctor[${`(A..N - 2, *, *)`}] =
24-
- new Bifunctor[${`(A..N - 2, *, *)`}] {
25-
- 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))
26-
- }"""
27-
else
28-
block"""
29-
-"""}
29+
- instance[${`(A..N - 2, *, *)`}] { (fab, f, g) =>
30+
- fab.copy(_${arity - 1} = f(fab._${arity - 1}), _$arity = g(fab._$arity))
31+
- }
3032
|}"""
3133
}
3234
}

project/TupleBitraverseInstancesBoiler.scala

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Boilerplate.{Template, TemplateVals}
55
import sbt.File
66

77
object GenTupleBitraverseInstances extends Template {
8-
override def range = 1 to 11
8+
override def range = 2 to 11
99
override def filename(root: sbt.File): File =
1010
root / "cats" / "instances" / "NTupleBitraverseInstances.scala"
1111

@@ -18,20 +18,35 @@ object GenTupleBitraverseInstances extends Template {
1818
|package instances
1919
|
2020
|private[cats] trait NTupleBitraverseInstances {
21-
${if (arity > 1)
22-
block"""
21+
| protected type γ[_]
22+
|
23+
| private def instance[F[_, _] <: Product](
24+
| bitrav: (F[Any, Any], Applicative[γ], Any => γ[Any], Any => γ[Any]) => γ[F[Any, Any]]
25+
| ): Bitraverse[F] = new Bitraverse[F] {
26+
| 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]] =
27+
| bitrav(
28+
| fab.asInstanceOf[F[Any, Any]],
29+
| G.asInstanceOf[Applicative[γ]],
30+
| f.asInstanceOf[Any => γ[Any]],
31+
| g.asInstanceOf[Any => γ[Any]]
32+
| ).asInstanceOf[G[F[C, D]]]
33+
|
34+
| @inline private def last1[A, B](fab: F[A, B]): A =
35+
| fab.productElement(fab.productArity - 2).asInstanceOf[A]
36+
| @inline private def last2[A, B](fab: F[A, B]): B =
37+
| fab.productElement(fab.productArity - 1).asInstanceOf[B]
38+
| def bifoldLeft[A, B, C](fab: F[A, B], c: C)(f: (C, A) => C, g: (C, B) => C): C =
39+
| g(f(c, last1(fab)), last2(fab))
40+
| 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] =
41+
| g(last2(fab), f(last1(fab), c))
42+
| }
43+
-
2344
- implicit final def catsStdBitraverseForTuple$arity${`[A0, A(N - 2)]`}: Bitraverse[${`(A..N - 2, *, *)`}] =
24-
- new Bitraverse[${`(A..N - 2, *, *)`}] {
25-
- 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)] =
26-
- G.tuple$arity(${`pure(fa._1..(n - 2))`}f(fa._${arity - 1}), g(fa._$arity))
27-
- def bifoldLeft[A, B, C](fa: (${`A0, A(N - 2)`}A, B), c: C)(f: (C, A) => C, g: (C, B) => C): C =
28-
- g(f(c, fa._${arity - 1}), fa._$arity)
29-
- 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] =
30-
- g(fa._$arity, f(fa._${arity - 1}, c))
31-
- }"""
32-
else
33-
block"""
34-
-"""}
45+
- instance { (fab, G, f, g) =>
46+
- G.map2(f(fab._${arity - 1}), g(fab._$arity)) { (x, y) =>
47+
- fab.copy(_${arity - 1} = x, _$arity = y)
48+
- }
49+
- }
3550
|}"""
3651
}
3752
}

project/TupleMonadInstancesBoiler.scala

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,49 +56,47 @@ object GenTupleMonadInstances extends Template {
5656
|import scala.annotation.tailrec
5757
|
5858
|private[cats] trait NTupleMonadInstances extends NTupleMonadInstances1 {
59+
|
60+
| private def instance[F[_] <: Product](cofMap: (F[Any], F[Any] => Any) => F[Any]): Comonad[F] =
61+
| new Comonad[F] {
62+
| def coflatMap[A, B](fa: F[A])(f: F[A] => B) =
63+
| cofMap(fa.asInstanceOf[F[Any]], f.asInstanceOf[F[Any] => Any]).asInstanceOf[F[B]]
64+
| def extract[A](fa: F[A]) =
65+
| fa.productElement(fa.productArity - 1).asInstanceOf[A]
66+
| def map[A, B](fa: F[A])(f: A => B) =
67+
| coflatMap(fa)(fa => f(extract(fa)))
68+
| }
69+
-
5970
- implicit final def catsStdInstancesForTuple$arity${`[A0, A(N - 1)]`}: Comonad[${`(A..N - 1, *)`}] =
60-
- new Comonad[${`(A..N - 1, *)`}] {
61-
- def coflatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: (${`A0, A(N - 1)&`("A")}) => B): ${`A0, A(N - 1)&`(
62-
"B"
63-
)} = ${`fa._1..(n - 1) & `(
64-
"f(fa)"
65-
)}
66-
- def extract[A](fa: ${`A0, A(N - 1)&`("A")}): A = fa._$arity
67-
- override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} =
68-
- ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
69-
- override def coflatten[A](fa: ${`A0, A(N - 1)&`("A")}): $coflattenReturn = ${`fa._1..(n - 1) & `("fa")}
70-
- }
71+
- instance((fa, f) => fa.copy(_$arity = f(fa)))
7172
|}
72-
|private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 {
73+
|private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 { this: NTupleMonadInstances =>
7374
- implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`(
7475
"CommutativeMonoid"
7576
)}: CommutativeMonad[${`(A..N - 1, *)`}] =
7677
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeMonad[${`(A..N - 1, *)`}] {
7778
- def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod
7879
- }
7980
|}
80-
|private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 {
81+
|private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 { this: NTupleMonadInstances =>
8182
- implicit final def catsStdCommutativeFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`(
8283
"CommutativeSemigroup"
8384
)}: CommutativeFlatMap[${`(A..N - 1, *)`}] =
8485
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with CommutativeFlatMap[${`(A..N - 1, *)`}]
8586
|}
86-
|private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 {
87+
|private[cats] sealed trait NTupleMonadInstances3 extends NTupleMonadInstances4 { this: NTupleMonadInstances =>
8788
- implicit def catsStdMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`("Monoid")}: Monad[${`(A..N - 1, *)`}] =
8889
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`}) with Monad[${`(A..N - 1, *)`}] {
8990
- def pure[A](a: A): ${`A0, A(N - 1)&`("A")} = $monadPureMethod
9091
- }
9192
|}
92-
|private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 {
93+
|private[cats] sealed trait NTupleMonadInstances4 extends NTupleMonadInstances5 { this: NTupleMonadInstances =>
9394
- implicit def catsStdFlatMapForTuple$arity${`[A0, A(N - 1)]`}${`constraints A..(N-1)`("Semigroup")}: FlatMap[${`(A..N - 1, *)`}] =
9495
- new FlatMapTuple$arity${`[A0, A(N - 1)]`}(${`A0, A(N - 1)`})
9596
|}
96-
|private[cats] sealed trait NTupleMonadInstances5 {
97+
|private[cats] sealed trait NTupleMonadInstances5 { this: NTupleMonadInstances =>
9798
- implicit def catsStdInvariantForTuple$arity${`[A0, A(N - 1)]`}: Invariant[${`(A..N - 1, *)`}] =
98-
- new Invariant[${`(A..N - 1, *)`}] {
99-
- def imap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: B => A): ${`A0, A(N - 1)&`("B")} =
100-
- ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
101-
- }
99+
- catsStdInstancesForTuple$arity
102100
|}
103101
-
104102
-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 {
107105
- override def product[A, B](fa: ${`A0, A(N - 1)&`("A")}, fb: ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("(A, B)")} =
108106
- ${`combine A..(N - 1)`("fa", "fb", s"(fa._$arity, fb._$arity)")}
109107
- override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} =
110-
- ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
108+
- fa.copy(_$arity = f(fa._$arity))
111109
- def flatMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => ${`A0, A(N - 1)&`("B")}): ${`A0, A(N - 1)&`("B")} = {
112110
${if (arity > 1) block"""
113111
- val xb = f(fa._$arity)

project/TupleShowInstancesBoiler.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ object GenTupleShowInstances extends Template {
2626
|
2727
|private[cats] trait NTupleShowInstances {
2828
- implicit final def catsStdShowForTuple$arity[${`A..N`}]${`constraints A..N`("Show")}: Show[${`(A..N)`}] =
29-
- new Show[${`(A..N)`}] {
30-
- def show(f: ${`(A..N)`}): String = $showMethod
31-
- }
29+
- f => $showMethod
3230
|}"""
3331
}
3432
}

project/TupleUnorderedFoldableInstancesBoiler.scala

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,37 @@ object GenTupleUnorderedFoldableInstances extends Template {
1818
|package instances
1919
|
2020
|private[cats] trait NTupleUnorderedFoldableInstances {
21-
- implicit final def catsUnorderedFoldableInstancesForTuple$arity${`[A0, A(N - 1)]`}: Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] =
22-
- new Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}] {
23-
- def traverse[G[_], A, B](fa: ${`A0, A(N - 1)&`(
24-
"A"
25-
)})(f: A => G[B])(implicit G: Applicative[G]): G[${`A0, A(N - 1)&`(
26-
"B"
27-
)}] =
28-
- G.map(f(fa._$arity))(${`(fa._1..(n - 1))`})
29-
- def foldLeft[A, B](fa: ${`A0, A(N - 1)&`("A")}, b: B)(f: (B, A) => B): B = f(b, fa._$arity)
30-
- 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)
31-
- override def map[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B): ${`A0, A(N - 1)&`("B")} =
32-
- ${`fa._1..(n - 1) & `(s"f(fa._$arity)")}
33-
- override def foldMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(implicit B: Monoid[B]): B = f(fa._$arity)
34-
- override def reduce[A](fa: ${`A0, A(N - 1)&`("A")})(implicit A: Semigroup[A]): A = fa._$arity
35-
- def reduceLeftTo[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (B, A) => B): B = f(fa._$arity)
36-
- override def reduceLeft[A](fa: ${`A0, A(N - 1)&`("A")})(f: (A, A) => A): A = fa._$arity
37-
- override def reduceLeftToOption[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(g: (B, A) => B): Option[B] = Some(f(fa._$arity))
38-
- override def reduceRight[A](fa: ${`A0, A(N - 1)&`("A")})(f: (A, Eval[A]) => Eval[A]): Eval[A] = Now(fa._$arity)
39-
- 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))
40-
- 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)))
41-
- override def reduceMap[A, B](fa: ${`A0, A(N - 1)&`("A")})(f: A => B)(implicit B: Semigroup[B]): B = f(fa._$arity)
42-
- override def size[A](fa: ${`A0, A(N - 1)&`("A")}): Long = 1L
43-
- override def get[A](fa: ${`A0, A(N - 1)&`("A")})(idx: Long): Option[A] = if (idx == 0L) Some(fa._$arity) else None
44-
- override def exists[A](fa: ${`A0, A(N - 1)&`("A")})(p: A => Boolean): Boolean = p(fa._$arity)
45-
- override def forall[A](fa: ${`A0, A(N - 1)&`("A")})(p: A => Boolean): Boolean = p(fa._$arity)
46-
- override def isEmpty[A](fa: ${`A0, A(N - 1)&`("A")}): Boolean = false
47-
- }
21+
| protected type γ[_]
22+
|
23+
| private def instance[F[_] <: Product](
24+
| trav: (F[Any], Applicative[γ], Any => γ[Any]) => γ[F[Any]]
25+
| ): Traverse[F] with Reducible[F] =
26+
| new Traverse[F] with Reducible[F] {
27+
| def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]) =
28+
| trav(fa.asInstanceOf[F[Any]], G.asInstanceOf[Applicative[γ]], f.asInstanceOf[Any => γ[Any]]).asInstanceOf[G[F[B]]]
29+
| @inline private def last[A](fa: F[A]): A =
30+
| fa.productElement(fa.productArity - 1).asInstanceOf[A]
31+
| def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = f(b, last(fa))
32+
| def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = f(last(fa), lb)
33+
| override def foldMap[A, B](fa: F[A])(f: A => B)(implicit B: Monoid[B]): B = f(last(fa))
34+
| override def reduce[A](fa: F[A])(implicit A: Semigroup[A]): A = last(fa)
35+
| def reduceLeftTo[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): B = f(last(fa))
36+
| override def reduceLeft[A](fa: F[A])(f: (A, A) => A): A = last(fa)
37+
| override def reduceLeftToOption[A, B](fa: F[A])(f: A => B)(g: (B, A) => B): Option[B] = Some(f(last(fa)))
38+
| override def reduceRight[A](fa: F[A])(f: (A, Eval[A]) => Eval[A]): Eval[A] = Now(last(fa))
39+
| def reduceRightTo[A, B](fa: F[A])(f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] = Now(f(last(fa)))
40+
| 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))))
41+
| override def reduceMap[A, B](fa: F[A])(f: A => B)(implicit B: Semigroup[B]): B = f(last(fa))
42+
| override def size[A](fa: F[A]): Long = 1L
43+
| override def get[A](fa: F[A])(idx: Long): Option[A] = if (idx == 0L) Some(last(fa)) else None
44+
| override def exists[A](fa: F[A])(p: A => Boolean): Boolean = p(last(fa))
45+
| override def forall[A](fa: F[A])(p: A => Boolean): Boolean = p(last(fa))
46+
| override def isEmpty[A](fa: F[A]): Boolean = false
47+
| }
48+
-
49+
- implicit final def catsUnorderedFoldableInstancesForTuple$arity${`[A0, A(N - 1)]`}
50+
- : Traverse[${`(A..N - 1, *)`}] with Reducible[${`(A..N - 1, *)`}]
51+
- = instance((fa, G, f) => G.map(f(fa._$arity))(x => fa.copy(_$arity = x)))
4852
|}"""
4953
}
5054
}

0 commit comments

Comments
 (0)