@@ -11,21 +11,23 @@ object Deriving {
11
11
/** The Generic class hierarchy allows typelevel access to
12
12
* enums, case classes and objects, and their sealed parents.
13
13
*/
14
- sealed abstract class Mirror [T ]
14
+ sealed abstract class Mirror { type MirroredType }
15
+
16
+ type MirrorOf [T ] = Mirror { type MirroredType = T }
15
17
16
18
object Mirror {
17
19
18
20
/** The Mirror for a sum type */
19
- trait Sum [ T ] extends Mirror [ T ] { self =>
21
+ trait Sum extends Mirror { self =>
20
22
21
23
type ElemTypes <: Tuple
22
24
23
25
/** The ordinal number of the case class of `x`. For enums, `ordinal(x) == x.ordinal` */
24
- def ordinal (x : T ): Int
26
+ def ordinal (x : MirroredType ): Int
25
27
}
26
28
27
29
/** The Mirror for a product type */
28
- trait Product [ T ] extends Mirror [ T ] {
30
+ trait Product extends Mirror {
29
31
30
32
/** The types of the elements */
31
33
type ElemTypes <: Tuple
@@ -37,8 +39,11 @@ object Deriving {
37
39
type ElemLabels <: Tuple
38
40
39
41
/** Create a new instance of type `T` with elements taken from product `p`. */
40
- def fromProduct (p : scala.Product ): T
42
+ def fromProduct (p : scala.Product ): MirroredType
41
43
}
44
+
45
+ type SumOf [T ] = Sum { type MirroredType = T }
46
+ type ProductOf [T ] = Product { type MirroredType = T }
42
47
}
43
48
44
49
/** Helper class to turn arrays into products */
@@ -61,37 +66,43 @@ import Deriving._
61
66
62
67
sealed trait Lst [+ T ] // derives Eq, Pickler, Show
63
68
64
- object Lst extends Mirror .Sum [Lst [_]] {
69
+ object Lst extends Mirror .Sum {
70
+ type MirroredType = Lst [_]
65
71
66
72
def ordinal (x : Lst [_]) = x match {
67
73
case x : Cons [_] => 0
68
74
case Nil => 1
69
75
}
70
76
71
- implicit def mirror [T ]: Mirror .Sum [Lst [T ]] {
77
+ implicit def mirror [T ]: Mirror .Sum {
78
+ type MirroredType = Lst [T ]
72
79
type ElemTypes = (Cons [T ], Nil .type )
73
80
} = this .asInstanceOf
74
81
75
82
case class Cons [T ](hd : T , tl : Lst [T ]) extends Lst [T ]
76
83
77
- object Cons extends Mirror .Product [Cons [_]] {
84
+ object Cons extends Mirror .Product {
85
+ type MirroredType = Cons [_]
78
86
79
87
def apply [T ](x : T , xs : Lst [T ]): Lst [T ] = new Cons (x, xs)
80
88
81
89
def fromProduct (p : Product ): Cons [_] =
82
90
new Cons (productElement[Any ](p, 0 ), productElement[Lst [Any ]](p, 1 ))
83
91
84
- implicit def mirror [T ]: Mirror .Product [Cons [T ]] {
92
+ implicit def mirror [T ]: Mirror .Product {
93
+ type MirroredType = Cons [T ]
85
94
type ElemTypes = (T , Lst [T ])
86
95
type CaseLabel = " Cons"
87
96
type ElemLabels = (" hd" , " tl" )
88
97
} = this .asInstanceOf
89
98
}
90
99
91
- case object Nil extends Lst [Nothing ] with Mirror .Product [Nil .type ] {
100
+ case object Nil extends Lst [Nothing ] with Mirror .Product {
101
+ type MirroredType = Nil .type
92
102
def fromProduct (p : Product ): Nil .type = Nil
93
103
94
- implicit def mirror : Mirror .Product [Nil .type ] {
104
+ implicit def mirror : Mirror .Product {
105
+ type MirroredType = Nil .type
95
106
type ElemTypes = Unit
96
107
type CaseLabel = " Nil"
97
108
type ElemLabels = Unit
@@ -108,12 +119,14 @@ object Lst extends Mirror.Sum[Lst[_]] {
108
119
109
120
case class Pair [T ](x : T , y : T ) // derives Eq, Pickler, Show
110
121
111
- object Pair extends Mirror .Product [Pair [_]] {
122
+ object Pair extends Mirror .Product {
123
+ type MirroredType = Pair [_]
112
124
113
125
def fromProduct (p : Product ): Pair [_] =
114
126
Pair (productElement[Any ](p, 0 ), productElement[Any ](p, 1 ))
115
127
116
- implicit def mirror [T ]: Mirror .Product [Pair [T ]] {
128
+ implicit def mirror [T ]: Mirror .Product {
129
+ type MirroredType = Pair [T ]
117
130
type ElemTypes = (T , T )
118
131
type CaseLabel = " Pair"
119
132
type ElemLabels = (" x" , " y" )
@@ -129,14 +142,16 @@ object Pair extends Mirror.Product[Pair[_]] {
129
142
130
143
sealed trait Either [+ L , + R ] extends Product with Serializable // derives Eq, Pickler, Show
131
144
132
- object Either extends Mirror .Sum [Either [_, _]] {
145
+ object Either extends Mirror .Sum {
146
+ type MirroredType = Either [_, _]
133
147
134
148
def ordinal (x : Either [_, _]) = x match {
135
149
case x : Left [_] => 0
136
150
case x : Right [_] => 1
137
151
}
138
152
139
- implicit def mirror [L , R ]: Mirror .Sum [Either [L , R ]] {
153
+ implicit def mirror [L , R ]: Mirror .Sum {
154
+ type MirroredType = Either [L , R ]
140
155
type ElemTypes = (Left [L ], Right [R ])
141
156
} = this .asInstanceOf
142
157
@@ -148,18 +163,22 @@ object Either extends Mirror.Sum[Either[_, _]] {
148
163
case class Left [L ](elem : L ) extends Either [L , Nothing ]
149
164
case class Right [R ](elem : R ) extends Either [Nothing , R ]
150
165
151
- object Left extends Mirror .Product [Left [_]] {
166
+ object Left extends Mirror .Product {
167
+ type MirroredType = Left [_]
152
168
def fromProduct (p : Product ): Left [_] = Left (productElement[Any ](p, 0 ))
153
- implicit def mirror [L ]: Mirror .Product [Left [L ]] {
169
+ implicit def mirror [L ]: Mirror .Product {
170
+ type MirroredType = Left [L ]
154
171
type ElemTypes = L *: Unit
155
172
type CaseLabel = " Left"
156
173
type ElemLabels = " x" *: Unit
157
174
} = this .asInstanceOf
158
175
}
159
176
160
- object Right extends Mirror .Product [Right [_]] {
177
+ object Right extends Mirror .Product {
178
+ type MirroredType = Right [_]
161
179
def fromProduct (p : Product ): Right [_] = Right (productElement[Any ](p, 0 ))
162
- implicit def mirror [R ]: Mirror .Product [Right [R ]] {
180
+ implicit def mirror [R ]: Mirror .Product {
181
+ type MirroredType = Right [R ]
163
182
type ElemTypes = R *: Unit
164
183
type CaseLabel = " Right"
165
184
type ElemLabels = " x" *: Unit
@@ -188,28 +207,28 @@ object Eq {
188
207
true
189
208
}
190
209
191
- inline def eqlProduct [T ](m : Mirror .Product [T ])(x : Any , y : Any ): Boolean =
210
+ inline def eqlProduct [T ](m : Mirror .ProductOf [T ])(x : Any , y : Any ): Boolean =
192
211
eqlElems[m.ElemTypes ](0 )(x, y)
193
212
194
213
inline def eqlCases [Alts ](n : Int )(x : Any , y : Any , ord : Int ): Boolean =
195
214
inline erasedValue[Alts ] match {
196
215
case _ : (alt *: alts1) =>
197
216
if (ord == n)
198
217
implicit match {
199
- case m : Mirror .Product [`alt`] => eqlElems[m.ElemTypes ](0 )(x, y)
218
+ case m : Mirror .ProductOf [`alt`] => eqlElems[m.ElemTypes ](0 )(x, y)
200
219
}
201
220
else eqlCases[alts1](n + 1 )(x, y, ord)
202
221
case _ : Unit =>
203
222
false
204
223
}
205
224
206
- inline def derived [T ](implicit ev : Mirror [T ]): Eq [T ] = new Eq [T ] {
225
+ inline def derived [T ](implicit ev : MirrorOf [T ]): Eq [T ] = new Eq [T ] {
207
226
def eql (x : T , y : T ): Boolean =
208
227
inline ev match {
209
- case m : Mirror .Sum [T ] =>
228
+ case m : Mirror .SumOf [T ] =>
210
229
val ord = m.ordinal(x)
211
230
ord == m.ordinal(y) && eqlCases[m.ElemTypes ](0 )(x, y, ord)
212
- case m : Mirror .Product [T ] =>
231
+ case m : Mirror .ProductOf [T ] =>
213
232
eqlElems[m.ElemTypes ](0 )(x, y)
214
233
}
215
234
}
@@ -248,7 +267,7 @@ object Pickler {
248
267
case _ : (alt *: alts1) =>
249
268
if (ord == n)
250
269
implicit match {
251
- case m : Mirror .Product [`alt`] => pickleElems[m.ElemTypes ](0 )(buf, x)
270
+ case m : Mirror .ProductOf [`alt`] => pickleElems[m.ElemTypes ](0 )(buf, x)
252
271
}
253
272
else pickleCases[alts1](n + 1 )(buf, x, ord)
254
273
case _ : Unit =>
@@ -266,7 +285,7 @@ object Pickler {
266
285
case _ : Unit =>
267
286
}
268
287
269
- inline def unpickleCase [T , Elems <: Tuple ](buf : mutable.ListBuffer [Int ], m : Mirror .Product [T ]): T = {
288
+ inline def unpickleCase [T , Elems <: Tuple ](buf : mutable.ListBuffer [Int ], m : Mirror .ProductOf [T ]): T = {
270
289
inline val size = constValue[Tuple .Size [Elems ]]
271
290
inline if (size == 0 )
272
291
m.fromProduct(EmptyProduct )
@@ -282,30 +301,30 @@ object Pickler {
282
301
case _ : (alt *: alts1) =>
283
302
if (ord == n)
284
303
implicit match {
285
- case m : Mirror .Product [`alt` & T ] =>
304
+ case m : Mirror .ProductOf [`alt` & T ] =>
286
305
unpickleCase[`alt` & T , m.ElemTypes ](buf, m)
287
306
}
288
307
else unpickleCases[T , alts1](n + 1 )(buf, ord)
289
308
case _ : Unit =>
290
309
throw new IndexOutOfBoundsException (s " unexpected ordinal number: $ord" )
291
310
}
292
311
293
- inline def derived [T ](implicit ev : Mirror [T ]): Pickler [T ] = new {
312
+ inline def derived [T ](implicit ev : MirrorOf [T ]): Pickler [T ] = new {
294
313
def pickle (buf : mutable.ListBuffer [Int ], x : T ): Unit =
295
314
inline ev match {
296
- case m : Mirror .Sum [T ] =>
315
+ case m : Mirror .SumOf [T ] =>
297
316
val ord = m.ordinal(x)
298
317
buf += ord
299
318
pickleCases[m.ElemTypes ](0 )(buf, x, ord)
300
- case m : Mirror .Product [T ] =>
319
+ case m : Mirror .ProductOf [T ] =>
301
320
pickleElems[m.ElemTypes ](0 )(buf, x)
302
321
}
303
322
def unpickle (buf : mutable.ListBuffer [Int ]): T =
304
323
inline ev match {
305
- case m : Mirror .Sum [T ] =>
324
+ case m : Mirror .SumOf [T ] =>
306
325
val ord = nextInt(buf)
307
326
unpickleCases[T , m.ElemTypes ](0 )(buf, ord)
308
- case m : Mirror .Product [T ] =>
327
+ case m : Mirror .ProductOf [T ] =>
309
328
unpickleCase[T , m.ElemTypes ](buf, m)
310
329
}
311
330
}
@@ -341,7 +360,7 @@ object Show {
341
360
Nil
342
361
}
343
362
344
- inline def showCase (x : Any , m : Mirror .Product [_]): String = {
363
+ inline def showCase (x : Any , m : Mirror .ProductOf [_]): String = {
345
364
val label = constValue[m.CaseLabel ]
346
365
showElems[m.ElemTypes , m.ElemLabels ](0 )(x).mkString(s " $label( " , " , " , " )" )
347
366
}
@@ -351,21 +370,21 @@ object Show {
351
370
case _ : (alt *: alts1) =>
352
371
if (ord == n)
353
372
implicit match {
354
- case m : Mirror .Product [`alt`] =>
373
+ case m : Mirror .ProductOf [`alt`] =>
355
374
showCase(x, m)
356
375
}
357
376
else showCases[alts1](n + 1 )(x, ord)
358
377
case _ : Unit =>
359
378
throw new MatchError (x)
360
379
}
361
380
362
- inline def derived [T ](implicit ev : Mirror [T ]): Show [T ] = new {
381
+ inline def derived [T ](implicit ev : MirrorOf [T ]): Show [T ] = new {
363
382
def show (x : T ): String =
364
383
inline ev match {
365
- case m : Mirror .Sum [T ] =>
384
+ case m : Mirror .SumOf [T ] =>
366
385
val ord = m.ordinal(x)
367
386
showCases[m.ElemTypes ](0 )(x, ord)
368
- case m : Mirror .Product [T ] =>
387
+ case m : Mirror .ProductOf [T ] =>
369
388
showCase(x, m)
370
389
}
371
390
}
0 commit comments