forked from typelevel/cats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTupleMonadInstancesBoiler.scala
156 lines (147 loc) · 6.8 KB
/
TupleMonadInstancesBoiler.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import sbt._
import Boilerplate._
import Boilerplate.{Template, TemplateVals}
import sbt.File
object GenTupleMonadInstances extends Template {
override def range = 1 to 11
override def filename(root: sbt.File): File =
root / "cats" / "instances" / "NTupleMonadInstances.scala"
override def content(tv: TemplateVals): String = {
import tv._
/**
* This special case for N = 2 is needed because
* of the deprecated versions in TupleInstances.
* It will be removed once the deprecated ones are
* deleted.
*/
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)"
else
`A..(N - 1)`.zipWithIndex.iterator
.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)"
else
`A..(N - 1)`.zipWithIndex.iterator
.map { case (an, i) =>
s"$an.combine(x._${i + 1}, a$i)"
}
.mkString(", ")
block"""
|
|package cats
|package instances
|
|import cats.kernel.{CommutativeMonoid, CommutativeSemigroup}
|import scala.annotation.tailrec
|
|private[cats] trait NTupleMonadInstances extends NTupleMonadInstances1 {
- 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")}
- }
|}
|private[cats] sealed trait NTupleMonadInstances1 extends NTupleMonadInstances2 {
- implicit final def catsStdCommutativeMonadForTuple$arity${`[A0, A(N - 1)]`}${`constraints 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
- }
|}
|private[cats] sealed trait NTupleMonadInstances2 extends NTupleMonadInstances3 {
- 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 {
- 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 {
- 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 {
- 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)")}
- }
|}
-
-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")} =
- ${`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)")} =
- ${`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)")}
- 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)
"""}
- }
- override def productR[A, B](a: ${`A0, A(N - 1)&`("A")})(b: ${`A0, A(N - 1)&`("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")} =
- ${`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)"
)} = {
- 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)
"""}
- }
- }
-}"""
}
}