0
# Helper Types for Type Class Testing
1
2
The Helper Types capability provides concrete data types where you can control exactly which type class instances are available. This enables precise testing of algebraic laws and type class behaviors.
3
4
## Overview
5
6
All helper types extend the base `N` trait and have controlled type class instances:
7
- All types include `Arbitrary[T]` and `Cogen[T]` for ScalaCheck property testing
8
- Each type provides exactly one primary algebraic type class instance
9
- Additional comparison instances (Eq, Order, etc.) are provided where appropriate
10
11
## Base Types and Traits
12
13
```scala { .api }
14
abstract class N {
15
def n: Int
16
}
17
18
abstract class Arb[E <: N](f: Int => E) {
19
implicit val earb: Arbitrary[E]
20
implicit val ccog: Cogen[E]
21
}
22
23
trait Q[E] {
24
implicit val eeq: Eq[E]
25
}
26
27
abstract class Companion[E <: N](f: Int => E) extends Arb[E](f) with Q[E]
28
```
29
30
## Equality and Ordering Types
31
32
### Eqed - Equality Only
33
For testing types that only need equality comparison.
34
35
```scala { .api }
36
case class Eqed(n: Int) extends N
37
object Eqed extends Companion(new Eqed(_))
38
```
39
40
**Usage example:**
41
```scala
42
import cats.tests.Helpers.Eqed
43
import cats.kernel.laws.discipline.EqTests
44
45
checkAll("Eq[Eqed]", EqTests[Eqed].eqv)
46
```
47
48
### POrd - Partial Order
49
For testing partial ordering laws where not all elements are comparable.
50
51
```scala { .api }
52
case class POrd(n: Int) extends N
53
object POrd extends Arb(new POrd(_)) {
54
implicit object O extends PartialOrder[POrd] {
55
def partialCompare(x: POrd, y: POrd): Double
56
}
57
}
58
```
59
60
**Usage example:**
61
```scala
62
import cats.tests.Helpers.POrd
63
import cats.kernel.laws.discipline.PartialOrderTests
64
65
checkAll("PartialOrder[POrd]", PartialOrderTests[POrd].partialOrder)
66
```
67
68
### Ord - Total Order
69
For testing total ordering laws.
70
71
```scala { .api }
72
case class Ord(n: Int) extends N
73
object Ord extends Arb(new Ord(_)) {
74
implicit object O extends Order[Ord] {
75
def compare(x: Ord, y: Ord): Int
76
}
77
}
78
```
79
80
**Usage example:**
81
```scala
82
import cats.tests.Helpers.Ord
83
import cats.kernel.laws.discipline.OrderTests
84
85
checkAll("Order[Ord]", OrderTests[Ord].order)
86
```
87
88
### Hsh - Hash
89
For testing hash-based equality.
90
91
```scala { .api }
92
case class Hsh(n: Int) extends N
93
object Hsh extends Arb(new Hsh(_)) {
94
implicit object O extends Hash[Hsh] {
95
def hash(x: Hsh): Int
96
def eqv(x: Hsh, y: Hsh): Boolean
97
}
98
}
99
```
100
101
## Algebraic Structure Types
102
103
### Band - Idempotent Semigroup
104
For testing idempotent semigroup laws (where `x combine x = x`).
105
106
```scala { .api }
107
case class Bnd(n: Int) extends N
108
object Bnd extends Companion(new Bnd(_)) {
109
implicit object Alg extends Band[Bnd] {
110
def combine(x: Bnd, y: Bnd): Bnd
111
}
112
}
113
```
114
115
### Semilattice
116
For testing semilattice laws (idempotent and commutative semigroup).
117
118
```scala { .api }
119
case class SL(n: Int) extends N
120
object SL extends Companion(new SL(_)) {
121
implicit object Alg extends Semilattice[SL] {
122
def combine(x: SL, y: SL): SL
123
}
124
}
125
```
126
127
### BoundedSemilattice
128
For testing bounded semilattice laws (semilattice with identity element).
129
130
```scala { .api }
131
case class BSL(n: Int) extends N
132
object BSL extends Companion(new BSL(_)) {
133
implicit object Alg extends BoundedSemilattice[BSL] {
134
def empty: BSL
135
def combine(x: BSL, y: BSL): BSL
136
}
137
}
138
```
139
140
### Semigroup
141
For testing basic semigroup laws (associativity).
142
143
```scala { .api }
144
case class Semi(n: Int) extends N
145
object Semi extends Companion(new Semi(_)) {
146
implicit object Alg extends Semigroup[Semi] {
147
def combine(x: Semi, y: Semi): Semi
148
}
149
}
150
```
151
152
### CommutativeSemigroup
153
For testing commutative semigroup laws.
154
155
```scala { .api }
156
case class CSemi(n: Int) extends N
157
object CSemi extends Companion(new CSemi(_)) {
158
implicit object Alg extends CommutativeSemigroup[CSemi] {
159
def combine(x: CSemi, y: CSemi): CSemi
160
}
161
}
162
```
163
164
### Monoid
165
For testing monoid laws (semigroup with identity).
166
167
```scala { .api }
168
case class Mono(n: Int) extends N
169
object Mono extends Companion(new Mono(_)) {
170
implicit object Alg extends Monoid[Mono] {
171
def empty: Mono
172
def combine(x: Mono, y: Mono): Mono
173
}
174
}
175
```
176
177
**Usage example:**
178
```scala
179
import cats.tests.Helpers.Mono
180
import cats.kernel.laws.discipline.MonoidTests
181
182
checkAll("Monoid[Mono]", MonoidTests[Mono].monoid)
183
```
184
185
### CommutativeMonoid
186
For testing commutative monoid laws.
187
188
```scala { .api }
189
case class CMono(n: Int) extends N
190
object CMono extends Companion(new CMono(_)) {
191
implicit object Alg extends CommutativeMonoid[CMono] {
192
def empty: CMono
193
def combine(x: CMono, y: CMono): CMono
194
}
195
}
196
```
197
198
### Group
199
For testing group laws (monoid with inverse).
200
201
```scala { .api }
202
case class Grp(n: Int) extends N
203
object Grp extends Companion(new Grp(_)) {
204
implicit object Alg extends Group[Grp] {
205
def empty: Grp
206
def combine(x: Grp, y: Grp): Grp
207
def inverse(x: Grp): Grp
208
}
209
}
210
```
211
212
**Usage example:**
213
```scala
214
import cats.tests.Helpers.Grp
215
import cats.kernel.laws.discipline.GroupTests
216
217
checkAll("Group[Grp]", GroupTests[Grp].group)
218
```
219
220
### CommutativeGroup
221
For testing commutative group laws.
222
223
```scala { .api }
224
case class CGrp(n: Int) extends N
225
object CGrp extends Companion(new CGrp(_)) {
226
implicit object Alg extends CommutativeGroup[CGrp] {
227
def empty: CGrp
228
def combine(x: CGrp, y: CGrp): CGrp
229
def inverse(x: CGrp): CGrp
230
}
231
}
232
```
233
234
## Testing Pattern
235
236
The typical pattern for using helper types in property-based testing:
237
238
```scala
239
import cats.tests.Helpers._
240
import cats.kernel.laws.discipline._
241
import org.scalatest.funsuite.AnyFunSuite
242
import org.scalatestplus.scalacheck.Checkers
243
244
class AlgebraicLawTests extends AnyFunSuite with Checkers {
245
246
test("semigroup laws") {
247
checkAll("Semigroup[Semi]", SemigroupTests[Semi].semigroup)
248
}
249
250
test("monoid laws") {
251
checkAll("Monoid[Mono]", MonoidTests[Mono].monoid)
252
}
253
254
test("group laws") {
255
checkAll("Group[Grp]", GroupTests[Grp].group)
256
}
257
}
258
```
259
260
Each helper type provides exactly the type class instances needed for testing specific algebraic laws, ensuring that tests focus on the intended algebraic structure without interference from additional instances.