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