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
```