Skip to content

Commit 1671eb7

Browse files
committed
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.
1 parent a03f973 commit 1671eb7

File tree

4 files changed

+97
-87
lines changed

4 files changed

+97
-87
lines changed

kernel/src/main/scala/cats/kernel/CommutativeGroup.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,14 @@ object CommutativeGroup extends GroupFunctions[CommutativeGroup] {
1414
* Access an implicit `CommutativeGroup[A]`.
1515
*/
1616
@inline final def apply[A](implicit ev: CommutativeGroup[A]): CommutativeGroup[A] = ev
17+
18+
/**
19+
* Create a `CommutativeGroup` instance from the given inverse and combine functions and empty value.
20+
*/
21+
@inline def instance[A](emp: A, inv: A => A, cmb: (A, A) => A): CommutativeGroup[A] =
22+
new CommutativeGroup[A] {
23+
val empty = emp
24+
def inverse(a: A) = inv(a)
25+
def combine(x: A, y: A) = cmb(x, y)
26+
}
1727
}

kernel/src/main/scala/cats/kernel/Group.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,14 @@ object Group extends GroupFunctions[Group] {
7474
* Access an implicit `Group[A]`.
7575
*/
7676
@inline final def apply[A](implicit ev: Group[A]): Group[A] = ev
77+
78+
/**
79+
* Create a `Group` instance from the given inverse and combine functions and empty value.
80+
*/
81+
@inline def instance[A](emp: A, inv: A => A, cmb: (A, A) => A): Group[A] =
82+
new Group[A] {
83+
val empty = emp
84+
def inverse(a: A) = inv(a)
85+
def combine(x: A, y: A) = cmb(x, y)
86+
}
7787
}

kernel/src/main/scala/cats/kernel/Hash.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,17 @@ object Hash extends HashFunctions[Hash] {
5454
def eqv(x: A, y: A) = x == y
5555
}
5656

57+
/**
58+
* Create a `Hash` instance from the given hash and equality functions.
59+
*/
60+
@inline def instance[A](h: A => Int, e: (A, A) => Boolean): Hash[A] =
61+
new Hash[A] {
62+
def hash(x: A) = h(x)
63+
def eqv(x: A, y: A) = e(x, y)
64+
}
5765
}
5866

5967
trait HashToHashingConversion {
6068
implicit def catsKernelHashToHashing[A](implicit ev: Hash[A]): Hashing[A] =
61-
new Hashing[A] {
62-
override def hash(x: A): Int = ev.hash(x)
63-
}
69+
ev.hash(_)
6470
}

project/KernelBoiler.scala

Lines changed: 68 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -143,21 +143,17 @@ object KernelBoiler {
143143
block"""
144144
| implicit def catsKernelStdCommutativeGroupForTuple$arity[${`A..N`}](
145145
| implicit ${constraints("CommutativeGroup")}
146-
| ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] {
147-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
148-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
149-
| def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
150-
| }
146+
| ): CommutativeGroup[${`(A..N)`}] =
147+
| Semigroup.catsKernelCommutativeGroupForTuple$arity[${`A..N`}]
151148
| implicit def catsKernelStdOrderForTuple$arity[${`A..N`}](
152149
| implicit ${constraints("Order")}
153-
| ): Order[${`(A..N)`}] = (x, y) =>
154-
| ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0)
150+
| ): Order[${`(A..N)`}] =
151+
| Eq.catsKernelOrderForTuple$arity[${`A..N`}]
155152
| implicit def catsKernelStdBoundedSemilatticeForTuple$arity[${`A..N`}](
156153
| implicit ${constraints("BoundedSemilattice")}
157-
| ): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] {
158-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
159-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
160-
| }"""
154+
| ): BoundedSemilattice[${`(A..N)`}] =
155+
| Semigroup.catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}]
156+
|"""
161157
}
162158
),
163159
InstanceDef(
@@ -170,33 +166,24 @@ object KernelBoiler {
170166
block"""
171167
| implicit def catsKernelStdSemilatticeForTuple$arity[${`A..N`}](
172168
| implicit ${constraints("Semilattice")}
173-
| ): Semilattice[${`(A..N)`}] = (x, y) =>
174-
| ${binTuple("combine")}
169+
| ): Semilattice[${`(A..N)`}] =
170+
| Semigroup.catsKernelSemilatticeForTuple$arity[${`A..N`}]
175171
| implicit def catsKernelStdCommutativeMonoidForTuple$arity[${`A..N`}](
176172
| implicit ${constraints("CommutativeMonoid")}
177-
| ): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] {
178-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
179-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
180-
| }
173+
| ): CommutativeMonoid[${`(A..N)`}] =
174+
| Semigroup.catsKernelCommutativeMonoidForTuple$arity[${`A..N`}]
181175
| implicit def catsKernelStdGroupForTuple$arity[${`A..N`}](
182176
| implicit ${constraints("Group")}
183-
| ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] {
184-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
185-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
186-
| def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
187-
| }
177+
| ): Group[${`(A..N)`}] =
178+
| Semigroup.catsKernelGroupForTuple$arity[${`A..N`}]
188179
| implicit def catsKernelStdHashForTuple$arity[${`A..N`}](
189180
| implicit ${constraints("Hash")}
190-
| ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] {
191-
| def hash(x: ${`(A..N)`}): Int =
192-
| ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode()
193-
| def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean =
194-
| ${binMethod("eqv").mkString(" && ")}
195-
| }
181+
| ): Hash[${`(A..N)`}] =
182+
| Eq.catsKernelHashForTuple$arity[${`A..N`}]
196183
| implicit def catsKernelStdPartialOrderForTuple$arity[${`A..N`}](
197184
| implicit ${constraints("PartialOrder")}
198-
| ): PartialOrder[${`(A..N)`}] = (x, y) =>
199-
| ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0)
185+
| ): PartialOrder[${`(A..N)`}] =
186+
| Eq.catsKernelPartialOrderForTuple$arity[${`A..N`}]
200187
|"""
201188
}
202189
),
@@ -210,18 +197,17 @@ object KernelBoiler {
210197
block"""
211198
| implicit def catsKernelStdBandForTuple$arity[${`A..N`}](
212199
| implicit ${constraints("Band")}
213-
| ): Band[${`(A..N)`}] = (x, y) =>
214-
| ${binTuple("combine")}
200+
| ): Band[${`(A..N)`}] =
201+
| Semigroup.catsKernelBandForTuple$arity[${`A..N`}]
215202
| implicit def catsKernelStdCommutativeSemigroupForTuple$arity[${`A..N`}](
216203
| implicit ${constraints("CommutativeSemigroup")}
217-
| ): CommutativeSemigroup[${`(A..N)`}] = (x, y) =>
218-
| ${binTuple("combine")}
204+
| ): CommutativeSemigroup[${`(A..N)`}] =
205+
| Semigroup.catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}]
219206
| implicit def catsKernelStdMonoidForTuple$arity[${`A..N`}](
220207
| implicit ${constraints("Monoid")}
221-
| ): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] {
222-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
223-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
224-
| }"""
208+
| ): Monoid[${`(A..N)`}] =
209+
| Semigroup.catsKernelMonoidForTuple$arity[${`A..N`}]
210+
|"""
225211
}
226212
),
227213
InstanceDef(
@@ -234,12 +220,12 @@ object KernelBoiler {
234220
block"""
235221
| implicit def catsKernelStdSemigroupForTuple$arity[${`A..N`}](
236222
| implicit ${constraints("Semigroup")}
237-
| ): Semigroup[${`(A..N)`}] = (x, y) =>
238-
| ${binTuple("combine")}
223+
| ): Semigroup[${`(A..N)`}] =
224+
| Semigroup.catsKernelSemigroupForTuple$arity[${`A..N`}]
239225
| implicit def catsKernelStdEqForTuple$arity[${`A..N`}](
240226
| implicit ${constraints("Eq")}
241-
| ): Eq[${`(A..N)`}] = (x, y) =>
242-
| ${binMethod("eqv").mkString(" && ")}
227+
| ): Eq[${`(A..N)`}] =
228+
| Eq.catsKernelEqForTuple$arity[${`A..N`}]
243229
|"""
244230
}
245231
),
@@ -252,9 +238,9 @@ object KernelBoiler {
252238
block"""
253239
| implicit def catsKernelBandForTuple$arity[${`A..N`}](
254240
| implicit ${constraints("Band")}
255-
| ): Band[${`(A..N)`}] = (x, y) =>
241+
| ): Band[${`(A..N)`}] = Band.instance { (x, y) =>
256242
| ${binTuple("combine")}
257-
|"""
243+
| }"""
258244
}
259245
),
260246
InstanceDef(
@@ -266,10 +252,10 @@ object KernelBoiler {
266252
block"""
267253
| implicit def catsKernelBoundedSemilatticeForTuple$arity[${`A..N`}](
268254
| implicit ${constraints("BoundedSemilattice")}
269-
| ): BoundedSemilattice[${`(A..N)`}] = new BoundedSemilattice[${`(A..N)`}] {
270-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
271-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
272-
| }"""
255+
| ): BoundedSemilattice[${`(A..N)`}] = BoundedSemilattice.instance(
256+
| ${nullaryTuple("empty")},
257+
| (x, y) => ${binTuple("combine")}
258+
| )"""
273259
}
274260
),
275261
InstanceDef(
@@ -281,11 +267,11 @@ object KernelBoiler {
281267
block"""
282268
| implicit def catsKernelCommutativeGroupForTuple$arity[${`A..N`}](
283269
| implicit ${constraints("CommutativeGroup")}
284-
| ): CommutativeGroup[${`(A..N)`}] = new CommutativeGroup[${`(A..N)`}] {
285-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
286-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
287-
| def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
288-
| }"""
270+
| ): CommutativeGroup[${`(A..N)`}] = CommutativeGroup.instance(
271+
| ${nullaryTuple("empty")},
272+
| x => ${unaryTuple("inverse")},
273+
| (x, y) => ${binTuple("combine")}
274+
| )"""
289275
}
290276
),
291277
InstanceDef(
@@ -297,10 +283,10 @@ object KernelBoiler {
297283
block"""
298284
| implicit def catsKernelCommutativeMonoidForTuple$arity[${`A..N`}](
299285
| implicit ${constraints("CommutativeMonoid")}
300-
| ): CommutativeMonoid[${`(A..N)`}] = new CommutativeMonoid[${`(A..N)`}] {
301-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
302-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
303-
| }"""
286+
| ): CommutativeMonoid[${`(A..N)`}] = CommutativeMonoid.instance(
287+
| ${nullaryTuple("empty")},
288+
| (x, y) => ${binTuple("combine")}
289+
| )"""
304290
}
305291
),
306292
InstanceDef(
@@ -312,9 +298,9 @@ object KernelBoiler {
312298
block"""
313299
| implicit def catsKernelCommutativeSemigroupForTuple$arity[${`A..N`}](
314300
| implicit ${constraints("CommutativeSemigroup")}
315-
| ): CommutativeSemigroup[${`(A..N)`}] = (x, y) =>
301+
| ): CommutativeSemigroup[${`(A..N)`}] = CommutativeSemigroup.instance { (x, y) =>
316302
| ${binTuple("combine")}
317-
|"""
303+
| }"""
318304
}
319305
),
320306
InstanceDef(
@@ -326,9 +312,9 @@ object KernelBoiler {
326312
block"""
327313
| implicit def catsKernelEqForTuple$arity[${`A..N`}](
328314
| implicit ${constraints("Eq")}
329-
| ): Eq[${`(A..N)`}] = (x, y) =>
315+
| ): Eq[${`(A..N)`}] = Eq.instance { (x, y) =>
330316
| ${binMethod("eqv").mkString(" && ")}
331-
|"""
317+
| }"""
332318
}
333319
),
334320
InstanceDef(
@@ -340,11 +326,11 @@ object KernelBoiler {
340326
block"""
341327
| implicit def catsKernelGroupForTuple$arity[${`A..N`}](
342328
| implicit ${constraints("Group")}
343-
| ): Group[${`(A..N)`}] = new Group[${`(A..N)`}] {
344-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
345-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
346-
| def inverse(x: ${`(A..N)`}): ${`(A..N)`} = ${unaryTuple("inverse")}
347-
| }"""
329+
| ): Group[${`(A..N)`}] = Group.instance(
330+
| ${nullaryTuple("empty")},
331+
| x => ${unaryTuple("inverse")},
332+
| (x, y) => ${binTuple("combine")}
333+
| )"""
348334
}
349335
),
350336
InstanceDef(
@@ -356,12 +342,10 @@ object KernelBoiler {
356342
block"""
357343
| implicit def catsKernelHashForTuple$arity[${`A..N`}](
358344
| implicit ${constraints("Hash")}
359-
| ): Hash[${`(A..N)`}] = new Hash[${`(A..N)`}] {
360-
| def hash(x: ${`(A..N)`}): Int =
361-
| ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode()
362-
| def eqv(x: ${`(A..N)`}, y: ${`(A..N)`}): Boolean =
363-
| ${binMethod("eqv").mkString(" && ")}
364-
| }"""
345+
| ): Hash[${`(A..N)`}] = Hash.instance(
346+
| x => ${unaryMethod("hash").mkString(s"$tupleNHeader(", ", ", ")")}.hashCode(),
347+
| (x, y) => ${binMethod("eqv").mkString(" && ")}
348+
| )"""
365349
}
366350
),
367351
InstanceDef(
@@ -373,10 +357,10 @@ object KernelBoiler {
373357
block"""
374358
| implicit def catsKernelMonoidForTuple$arity[${`A..N`}](
375359
| implicit ${constraints("Monoid")}
376-
| ): Monoid[${`(A..N)`}] = new Monoid[${`(A..N)`}] {
377-
| def combine(x: ${`(A..N)`}, y: ${`(A..N)`}): ${`(A..N)`} = ${binTuple("combine")}
378-
| def empty: ${`(A..N)`} = ${nullaryTuple("empty")}
379-
| }"""
360+
| ): Monoid[${`(A..N)`}] = Monoid.instance(
361+
| ${nullaryTuple("empty")},
362+
| (x, y) => ${binTuple("combine")}
363+
| )"""
380364
}
381365
),
382366
InstanceDef(
@@ -388,9 +372,9 @@ object KernelBoiler {
388372
block"""
389373
| implicit def catsKernelOrderForTuple$arity[${`A..N`}](
390374
| implicit ${constraints("Order")}
391-
| ): Order[${`(A..N)`}] = (x, y) =>
375+
| ): Order[${`(A..N)`}] = Order.from { (x, y) =>
392376
| ${binMethod("compare").mkString("Array(", ", ", ")")}.find(_ != 0).getOrElse(0)
393-
|"""
377+
| }"""
394378
}
395379
),
396380
InstanceDef(
@@ -402,9 +386,9 @@ object KernelBoiler {
402386
block"""
403387
| implicit def catsKernelPartialOrderForTuple$arity[${`A..N`}](
404388
| implicit ${constraints("PartialOrder")}
405-
| ): PartialOrder[${`(A..N)`}] = (x, y) =>
389+
| ): PartialOrder[${`(A..N)`}] = PartialOrder.from { (x, y) =>
406390
| ${binMethod("partialCompare").mkString("Array(", ", ", ")")}.find(_ != 0.0).getOrElse(0.0)
407-
|"""
391+
| }"""
408392
}
409393
),
410394
InstanceDef(
@@ -416,9 +400,9 @@ object KernelBoiler {
416400
block"""
417401
| implicit def catsKernelSemigroupForTuple$arity[${`A..N`}](
418402
| implicit ${constraints("Semigroup")}
419-
| ): Semigroup[${`(A..N)`}] = (x, y) =>
403+
| ): Semigroup[${`(A..N)`}] = Semigroup.instance { (x, y) =>
420404
| ${binTuple("combine")}
421-
|"""
405+
| }"""
422406
}
423407
),
424408
InstanceDef(
@@ -430,9 +414,9 @@ object KernelBoiler {
430414
block"""
431415
| implicit def catsKernelSemilatticeForTuple$arity[${`A..N`}](
432416
| implicit ${constraints("Semilattice")}
433-
| ): Semilattice[${`(A..N)`}] = (x, y) =>
417+
| ): Semilattice[${`(A..N)`}] = Semilattice.instance { (x, y) =>
434418
| ${binTuple("combine")}
435-
|"""
419+
| }"""
436420
}
437421
)
438422
)

0 commit comments

Comments
 (0)