@@ -27,7 +27,8 @@ object Boilerplate {
27
27
val templates : Seq [Template ] = Seq (
28
28
GenCartesianBuilders ,
29
29
GenCartesianArityFunctions ,
30
- GenApplyArityFunctions
30
+ GenApplyArityFunctions ,
31
+ GenTupleCartesianSyntax
31
32
)
32
33
33
34
val header = " // auto-generated boilerplate" // TODO: put something meaningful here?
@@ -60,12 +61,21 @@ object Boilerplate {
60
61
def content (tv : TemplateVals ): String
61
62
def range = 1 to maxArity
62
63
def body : String = {
63
- val headerLines = header split '\n '
64
+ def expandInstances (contents : IndexedSeq [Array [String ]], acc : Array [String ] = Array .empty): Array [String ] =
65
+ if (! contents.exists(_ exists(_ startsWith " -" )))
66
+ acc map (_.tail)
67
+ else {
68
+ val pre = contents.head takeWhile (_ startsWith " |" )
69
+ val instances = contents flatMap {_ dropWhile (_ startsWith " |" ) takeWhile (_ startsWith " -" ) }
70
+ val next = contents map {_ dropWhile (_ startsWith " |" ) dropWhile (_ startsWith " -" ) }
71
+ expandInstances(next, acc ++ pre ++ instances)
72
+ }
73
+
64
74
val rawContents = range map { n => content(new TemplateVals (n)) split '\n ' filterNot (_.isEmpty) }
65
- val preBody = rawContents.head takeWhile (_ startsWith " | " ) map (_.tail)
66
- val instances = rawContents flatMap {_ filter (_ startsWith " - " ) map (_.tail) }
67
- val postBody = rawContents.head dropWhile (_ startsWith " |" ) dropWhile (_ startsWith " - " ) map (_.tail)
68
- (headerLines ++ preBody ++ instances ++ postBody ) mkString " \n "
75
+ val headerLines = header split ' \n '
76
+ val instances = expandInstances(rawContents)
77
+ val footerLines = rawContents.head.reverse.takeWhile (_ startsWith " |" ). map(_.tail).reverse
78
+ (headerLines ++ instances ++ footerLines ) mkString " \n "
69
79
}
70
80
}
71
81
@@ -211,4 +221,52 @@ object Boilerplate {
211
221
}
212
222
}
213
223
224
+ object GenTupleCartesianSyntax extends Template {
225
+ def filename (root : File ) = root / " cats" / " syntax" / " TupleCartesianSyntax.scala"
226
+
227
+ def content (tv : TemplateVals ) = {
228
+ import tv ._
229
+
230
+ val tpes = synTypes map { tpe => s " F[ $tpe] " }
231
+ val tpesString = tpes mkString " , "
232
+
233
+ val tuple = s " Tuple $arity[ $tpesString] "
234
+ val tupleTpe = s " t $arity: $tuple"
235
+ val tupleArgs = (1 to arity) map { case n => s " t $arity._ $n" } mkString " , "
236
+
237
+ val n = if (arity == 1 ) { " " } else { arity.toString }
238
+
239
+ val map =
240
+ if (arity == 1 ) s " def map[Z](f: ( ${`A..N`}) => Z)(implicit functor: Functor[F]): F[Z] = functor.map( $tupleArgs)(f) "
241
+ else s " def map $arity[Z](f: ( ${`A..N`}) => Z)(implicit functor: Functor[F], cartesian: Cartesian[F]): F[Z] = Cartesian.map $arity( $tupleArgs)(f) "
242
+
243
+ val contramap =
244
+ if (arity == 1 ) s " def contramap[Z](f: Z => ( ${`A..N`}))(implicit contravariant: Contravariant[F]): F[Z] = contravariant.contramap( $tupleArgs)(f) "
245
+ else s " def contramap $arity[Z](f: Z => ( ${`A..N`}))(implicit contravariant: Contravariant[F], cartesian: Cartesian[F]): F[Z] = Cartesian.contramap $arity( $tupleArgs)(f) "
246
+
247
+ val imap =
248
+ if (arity == 1 ) s " def imap[Z](f: ( ${`A..N`}) => Z)(g: Z => ( ${`A..N`}))(implicit invariant: Invariant[F]): F[Z] = invariant.imap( $tupleArgs)(f)(g) "
249
+ else s " def imap $arity[Z](f: ( ${`A..N`}) => Z)(g: Z => ( ${`A..N`}))(implicit invariant: Invariant[F], cartesian: Cartesian[F]): F[Z] = Cartesian.imap $arity( $tupleArgs)(f)(g) "
250
+
251
+ block """
252
+ |package cats
253
+ |package syntax
254
+ |
255
+ |import cats.functor.{Contravariant, Invariant}
256
+ |
257
+ |trait TupleCartesianSyntax {
258
+ - implicit def catsSyntaxTuple ${arity}Cartesian[F[_], ${`A..N`}]( $tupleTpe): Tuple ${arity}CartesianOps[F, ${`A..N`}] = new Tuple ${arity}CartesianOps(t $arity)
259
+ |}
260
+ |
261
+ -private[syntax] final class Tuple ${arity}CartesianOps[F[_], ${`A..N`}]( $tupleTpe) {
262
+ - $map
263
+ - $contramap
264
+ - $imap
265
+ - def apWith[Z](f: F[( ${`A..N`}) => Z])(implicit apply: Apply[F]): F[Z] = apply.ap $n(f)( $tupleArgs)
266
+ -}
267
+ |
268
+ """
269
+ }
270
+ }
271
+
214
272
}
0 commit comments