or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

helper-types.mdindex.mdlist-wrapper.md

helper-types.mddocs/

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.