or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdcapabilities.mdcollections.mdcore-types.mdderivation.mdindex.mdmetaprogramming.mdruntime.mdutilities.md

derivation.mddocs/

0

# Derivation System

1

2

Mirror-based generic programming for automatic derivation of type class instances, supporting both sum types (enums) and product types (case classes).

3

4

## Capabilities

5

6

### Mirror Types

7

8

Core mirror types for compile-time reflection and generic programming.

9

10

```scala { .api }

11

/**

12

* Base trait for compile-time reflection of types

13

* Provides type-level access to the structure of enums, case classes, and objects

14

*/

15

sealed trait Mirror:

16

/** The type being mirrored */

17

type MirroredMonoType

18

/** String name of the mirrored type */

19

type MirroredLabel <: String

20

/** Tuple of element names (field names for products, case names for sums) */

21

type MirroredElemLabels <: Tuple

22

23

/**

24

* Mirror for sum types (sealed traits, enums)

25

* Provides ordinal access to sum type variants

26

*/

27

trait Mirror.Sum extends Mirror:

28

/** Get ordinal (index) of sum type instance */

29

def ordinal(x: MirroredMonoType): Int

30

31

/**

32

* Mirror for product types (case classes, tuples)

33

* Provides construction from generic product representation

34

*/

35

trait Mirror.Product extends Mirror:

36

/** Element types of the product */

37

type MirroredElemTypes <: Tuple

38

/** Create instance from product representation */

39

def fromProduct(p: scala.Product): MirroredMonoType

40

41

/**

42

* Mirror for singleton types (objects, case objects)

43

*/

44

trait Mirror.Singleton extends Mirror.Product:

45

type MirroredElemTypes = EmptyTuple

46

def fromProduct(p: scala.Product): MirroredMonoType

47

48

/**

49

* Mirror proxy for Scala 2 compatibility

50

*/

51

trait Mirror.SingletonProxy extends Mirror.Singleton

52

```

53

54

**Type Aliases:**

55

56

```scala { .api }

57

object Mirror:

58

/** Mirror of any kind for type T */

59

type Of[T] = Mirror { type MirroredMonoType = T }

60

/** Product mirror for type T */

61

type ProductOf[T] = Mirror.Product { type MirroredMonoType = T }

62

/** Sum mirror for type T */

63

type SumOf[T] = Mirror.Sum { type MirroredMonoType = T }

64

```

65

66

**Usage Examples:**

67

68

```scala

69

import scala.deriving.Mirror

70

71

// Example types

72

enum Color:

73

case Red, Green, Blue

74

75

case class Person(name: String, age: Int)

76

77

case object Singleton

78

79

// Using mirrors

80

def showStructure[T](value: T)(using mirror: Mirror.Of[T]): String =

81

val typeName = constValue[mirror.MirroredLabel]

82

s"Type: $typeName"

83

84

// Sum type mirror

85

def getOrdinal[T](value: T)(using mirror: Mirror.SumOf[T]): Int =

86

mirror.ordinal(value)

87

88

val red = Color.Red

89

println(getOrdinal(red)) // 0

90

91

// Product type mirror

92

def fromTuple[T](tuple: Tuple)(using mirror: Mirror.ProductOf[T]): T =

93

mirror.fromProduct(tuple.asInstanceOf[Product])

94

95

val personTuple = ("Alice", 30)

96

val person = fromTuple[Person](personTuple.asInstanceOf[Tuple])

97

```

98

99

### Generic Programming Patterns

100

101

Common patterns for writing generic code using mirrors.

102

103

```scala { .api }

104

// Type class derivation pattern

105

trait Show[T]:

106

def show(value: T): String

107

108

object Show:

109

/** Derive Show for product types */

110

inline def derived[T](using mirror: Mirror.ProductOf[T]): Show[T] =

111

new Show[T]:

112

def show(value: T): String =

113

val typeName = constValue[mirror.MirroredLabel]

114

val elemLabels = constValueTuple[mirror.MirroredElemLabels]

115

// Implementation details...

116

s"$typeName(...)"

117

118

/** Derive Show for sum types */

119

inline def derived[T](using mirror: Mirror.SumOf[T]): Show[T] =

120

new Show[T]:

121

def show(value: T): String =

122

val typeName = constValue[mirror.MirroredLabel]

123

val ordinal = mirror.ordinal(value)

124

s"$typeName#$ordinal"

125

```

126

127

**Usage Examples:**

128

129

```scala

130

// Automatic derivation

131

case class Point(x: Double, y: Double) derives Show

132

133

enum Status derives Show:

134

case Active, Inactive, Pending

135

136

// Using derived instances

137

val point = Point(1.0, 2.0)

138

println(summon[Show[Point]].show(point)) // "Point(...)"

139

140

val status = Status.Active

141

println(summon[Show[Status]].show(status)) // "Status#0"

142

143

// Manual derivation

144

given Show[Person] = Show.derived

145

146

val alice = Person("Alice", 30)

147

println(summon[Show[Person]].show(alice))

148

```

149

150

### Advanced Derivation Techniques

151

152

Advanced patterns for complex generic programming scenarios.

153

154

```scala { .api }

155

// Recursive derivation for nested structures

156

trait Eq[T]:

157

def eqv(x: T, y: T): Boolean

158

159

object Eq:

160

given Eq[String] = _ == _

161

given Eq[Int] = _ == _

162

given Eq[Boolean] = _ == _

163

164

given [T](using eq: Eq[T]): Eq[Option[T]] =

165

(x, y) => (x, y) match

166

case (Some(a), Some(b)) => eq.eqv(a, b)

167

case (None, None) => true

168

case _ => false

169

170

given [T](using eq: Eq[T]): Eq[List[T]] =

171

(xs, ys) => xs.length == ys.length && xs.zip(ys).forall(eq.eqv)

172

173

inline def derived[T](using mirror: Mirror.Of[T]): Eq[T] =

174

inline mirror match

175

case m: Mirror.SumOf[T] => derivedSum(using m)

176

case m: Mirror.ProductOf[T] => derivedProduct(using m)

177

178

private inline def derivedSum[T](using mirror: Mirror.SumOf[T]): Eq[T] =

179

(x, y) => mirror.ordinal(x) == mirror.ordinal(y) && x == y

180

181

private inline def derivedProduct[T](using mirror: Mirror.ProductOf[T]): Eq[T] =

182

(x, y) =>

183

val xProduct = Tuple.fromProductTyped(x)

184

val yProduct = Tuple.fromProductTyped(y)

185

compareProducts(xProduct, yProduct)

186

187

private def compareProducts[T <: Tuple](x: T, y: T): Boolean =

188

// Implementation for comparing tuple elements recursively

189

x == y // Simplified

190

```

191

192

**Usage Examples:**

193

194

```scala

195

// Derive equality for complex nested types

196

case class Address(street: String, city: String)

197

case class Person(name: String, age: Int, address: Address) derives Eq

198

199

val alice1 = Person("Alice", 30, Address("Main St", "NYC"))

200

val alice2 = Person("Alice", 30, Address("Main St", "NYC"))

201

val bob = Person("Bob", 25, Address("Oak Ave", "LA"))

202

203

println(summon[Eq[Person]].eqv(alice1, alice2)) // true

204

println(summon[Eq[Person]].eqv(alice1, bob)) // false

205

```

206

207

### Tuple Derivation Support

208

209

Utilities for working with tuples in generic programming.

210

211

```scala { .api }

212

object Tuple:

213

/** Convert any Product to a tuple with proper typing */

214

def fromProductTyped[P <: Product](p: P): Tuple =

215

fromProduct(p).asInstanceOf[Tuple]

216

217

/** Convert Product to untyped tuple */

218

def fromProduct(p: Product): Tuple =

219

// Convert product to tuple representation

220

???

221

222

/** Get size of tuple type at compile time */

223

inline def size[T <: Tuple]: Int = constValue[Size[T]]

224

225

/** Map over tuple with type-level function */

226

inline def map[T <: Tuple, F[_]](tuple: T)(f: [X] => X => F[X]): Map[T, F] = ???

227

```

228

229

**Usage Examples:**

230

231

```scala

232

// Working with products as tuples

233

case class Point3D(x: Double, y: Double, z: Double)

234

235

val point = Point3D(1.0, 2.0, 3.0)

236

val tuple = Tuple.fromProductTyped(point) // (1.0, 2.0, 3.0)

237

238

// Type-level size computation

239

type Coords = (Double, Double, Double)

240

val size = Tuple.size[Coords] // 3

241

242

// Type-level mapping

243

val optionalCoords = Tuple.map((1.0, 2.0, 3.0))(

244

[X] => (x: X) => Option(x)

245

) // (Some(1.0), Some(2.0), Some(3.0))

246

```

247

248

### Label Utilities

249

250

Working with compile-time labels and names.

251

252

```scala { .api }

253

/**

254

* Extract field names from a mirror as a tuple of strings

255

*/

256

inline def labelValues[T](using mirror: Mirror.Of[T]): Tuple =

257

constValueTuple[mirror.MirroredElemLabels]

258

259

/**

260

* Get type name as string

261

*/

262

inline def typeName[T](using mirror: Mirror.Of[T]): String =

263

constValue[mirror.MirroredLabel]

264

```

265

266

**Usage Examples:**

267

268

```scala

269

case class User(id: Int, name: String, email: String)

270

271

// Get field names at compile time

272

val fieldNames = labelValues[User] // ("id", "name", "email")

273

val className = typeName[User] // "User"

274

275

// Use in generic serialization

276

def toMap[T](value: T)(using mirror: Mirror.ProductOf[T]): Map[String, Any] =

277

val labels = labelValues[T].toArray.map(_.toString)

278

val values = Tuple.fromProductTyped(value).toArray

279

labels.zip(values).toMap

280

281

val user = User(1, "Alice", "alice@example.com")

282

val userMap = toMap(user)

283

// Map("id" -> 1, "name" -> "Alice", "email" -> "alice@example.com")

284

```

285

286

### Integration with Type Classes

287

288

Seamless integration with common type class patterns.

289

290

```scala { .api }

291

// Common derivable type classes work automatically

292

trait Ordering[T]:

293

def compare(x: T, y: T): Int

294

295

trait Encoder[T]:

296

def encode(value: T): String

297

298

trait Decoder[T]:

299

def decode(input: String): Either[String, T]

300

301

// Standard derives syntax works

302

case class Product(name: String, price: Double)

303

derives Eq, Show, Ordering, Encoder, Decoder

304

305

enum Priority derives Eq, Show, Ordering:

306

case Low, Medium, High

307

```

308

309

## Types

310

311

```scala { .api }

312

// Core mirror types

313

sealed trait Mirror:

314

type MirroredMonoType

315

type MirroredLabel <: String

316

type MirroredElemLabels <: Tuple

317

318

trait Mirror.Sum extends Mirror:

319

def ordinal(x: MirroredMonoType): Int

320

321

trait Mirror.Product extends Mirror:

322

type MirroredElemTypes <: Tuple

323

def fromProduct(p: scala.Product): MirroredMonoType

324

325

trait Mirror.Singleton extends Mirror.Product:

326

type MirroredElemTypes = EmptyTuple

327

328

trait Mirror.SingletonProxy extends Mirror.Singleton

329

330

// Type aliases

331

object Mirror:

332

type Of[T] = Mirror { type MirroredMonoType = T }

333

type ProductOf[T] = Mirror.Product { type MirroredMonoType = T }

334

type SumOf[T] = Mirror.Sum { type MirroredMonoType = T }

335

```