Skip to content

Commit c1fbed9

Browse files
committed
Make mirrored type a type member
Make mirrored type a type member instead of a type parameter, following Miles' design.
1 parent 36ae3b2 commit c1fbed9

File tree

1 file changed

+56
-37
lines changed

1 file changed

+56
-37
lines changed

tests/run/typeclass-derivation2d.scala

+56-37
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,23 @@ object Deriving {
1111
/** The Generic class hierarchy allows typelevel access to
1212
* enums, case classes and objects, and their sealed parents.
1313
*/
14-
sealed abstract class Mirror[T]
14+
sealed abstract class Mirror { type MirroredType }
15+
16+
type MirrorOf[T] = Mirror { type MirroredType = T }
1517

1618
object Mirror {
1719

1820
/** The Mirror for a sum type */
19-
trait Sum[T] extends Mirror[T] { self =>
21+
trait Sum extends Mirror { self =>
2022

2123
type ElemTypes <: Tuple
2224

2325
/** 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
2527
}
2628

2729
/** The Mirror for a product type */
28-
trait Product[T] extends Mirror[T] {
30+
trait Product extends Mirror {
2931

3032
/** The types of the elements */
3133
type ElemTypes <: Tuple
@@ -37,8 +39,11 @@ object Deriving {
3739
type ElemLabels <: Tuple
3840

3941
/** 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
4143
}
44+
45+
type SumOf[T] = Sum { type MirroredType = T }
46+
type ProductOf[T] = Product { type MirroredType = T }
4247
}
4348

4449
/** Helper class to turn arrays into products */
@@ -61,37 +66,43 @@ import Deriving._
6166

6267
sealed trait Lst[+T] // derives Eq, Pickler, Show
6368

64-
object Lst extends Mirror.Sum[Lst[_]] {
69+
object Lst extends Mirror.Sum {
70+
type MirroredType = Lst[_]
6571

6672
def ordinal(x: Lst[_]) = x match {
6773
case x: Cons[_] => 0
6874
case Nil => 1
6975
}
7076

71-
implicit def mirror[T]: Mirror.Sum[Lst[T]] {
77+
implicit def mirror[T]: Mirror.Sum {
78+
type MirroredType = Lst[T]
7279
type ElemTypes = (Cons[T], Nil.type)
7380
} = this.asInstanceOf
7481

7582
case class Cons[T](hd: T, tl: Lst[T]) extends Lst[T]
7683

77-
object Cons extends Mirror.Product[Cons[_]] {
84+
object Cons extends Mirror.Product {
85+
type MirroredType = Cons[_]
7886

7987
def apply[T](x: T, xs: Lst[T]): Lst[T] = new Cons(x, xs)
8088

8189
def fromProduct(p: Product): Cons[_] =
8290
new Cons(productElement[Any](p, 0), productElement[Lst[Any]](p, 1))
8391

84-
implicit def mirror[T]: Mirror.Product[Cons[T]] {
92+
implicit def mirror[T]: Mirror.Product {
93+
type MirroredType = Cons[T]
8594
type ElemTypes = (T, Lst[T])
8695
type CaseLabel = "Cons"
8796
type ElemLabels = ("hd", "tl")
8897
} = this.asInstanceOf
8998
}
9099

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
92102
def fromProduct(p: Product): Nil.type = Nil
93103

94-
implicit def mirror: Mirror.Product[Nil.type] {
104+
implicit def mirror: Mirror.Product {
105+
type MirroredType = Nil.type
95106
type ElemTypes = Unit
96107
type CaseLabel = "Nil"
97108
type ElemLabels = Unit
@@ -108,12 +119,14 @@ object Lst extends Mirror.Sum[Lst[_]] {
108119

109120
case class Pair[T](x: T, y: T) // derives Eq, Pickler, Show
110121

111-
object Pair extends Mirror.Product[Pair[_]] {
122+
object Pair extends Mirror.Product {
123+
type MirroredType = Pair[_]
112124

113125
def fromProduct(p: Product): Pair[_] =
114126
Pair(productElement[Any](p, 0), productElement[Any](p, 1))
115127

116-
implicit def mirror[T]: Mirror.Product[Pair[T]] {
128+
implicit def mirror[T]: Mirror.Product {
129+
type MirroredType = Pair[T]
117130
type ElemTypes = (T, T)
118131
type CaseLabel = "Pair"
119132
type ElemLabels = ("x", "y")
@@ -129,14 +142,16 @@ object Pair extends Mirror.Product[Pair[_]] {
129142

130143
sealed trait Either[+L, +R] extends Product with Serializable // derives Eq, Pickler, Show
131144

132-
object Either extends Mirror.Sum[Either[_, _]] {
145+
object Either extends Mirror.Sum {
146+
type MirroredType = Either[_, _]
133147

134148
def ordinal(x: Either[_, _]) = x match {
135149
case x: Left[_] => 0
136150
case x: Right[_] => 1
137151
}
138152

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]
140155
type ElemTypes = (Left[L], Right[R])
141156
} = this.asInstanceOf
142157

@@ -148,18 +163,22 @@ object Either extends Mirror.Sum[Either[_, _]] {
148163
case class Left[L](elem: L) extends Either[L, Nothing]
149164
case class Right[R](elem: R) extends Either[Nothing, R]
150165

151-
object Left extends Mirror.Product[Left[_]] {
166+
object Left extends Mirror.Product {
167+
type MirroredType = Left[_]
152168
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]
154171
type ElemTypes = L *: Unit
155172
type CaseLabel = "Left"
156173
type ElemLabels = "x" *: Unit
157174
} = this.asInstanceOf
158175
}
159176

160-
object Right extends Mirror.Product[Right[_]] {
177+
object Right extends Mirror.Product {
178+
type MirroredType = Right[_]
161179
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]
163182
type ElemTypes = R *: Unit
164183
type CaseLabel = "Right"
165184
type ElemLabels = "x" *: Unit
@@ -188,28 +207,28 @@ object Eq {
188207
true
189208
}
190209

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 =
192211
eqlElems[m.ElemTypes](0)(x, y)
193212

194213
inline def eqlCases[Alts](n: Int)(x: Any, y: Any, ord: Int): Boolean =
195214
inline erasedValue[Alts] match {
196215
case _: (alt *: alts1) =>
197216
if (ord == n)
198217
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)
200219
}
201220
else eqlCases[alts1](n + 1)(x, y, ord)
202221
case _: Unit =>
203222
false
204223
}
205224

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] {
207226
def eql(x: T, y: T): Boolean =
208227
inline ev match {
209-
case m: Mirror.Sum[T] =>
228+
case m: Mirror.SumOf[T] =>
210229
val ord = m.ordinal(x)
211230
ord == m.ordinal(y) && eqlCases[m.ElemTypes](0)(x, y, ord)
212-
case m: Mirror.Product[T] =>
231+
case m: Mirror.ProductOf[T] =>
213232
eqlElems[m.ElemTypes](0)(x, y)
214233
}
215234
}
@@ -248,7 +267,7 @@ object Pickler {
248267
case _: (alt *: alts1) =>
249268
if (ord == n)
250269
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)
252271
}
253272
else pickleCases[alts1](n + 1)(buf, x, ord)
254273
case _: Unit =>
@@ -266,7 +285,7 @@ object Pickler {
266285
case _: Unit =>
267286
}
268287

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 = {
270289
inline val size = constValue[Tuple.Size[Elems]]
271290
inline if (size == 0)
272291
m.fromProduct(EmptyProduct)
@@ -282,30 +301,30 @@ object Pickler {
282301
case _: (alt *: alts1) =>
283302
if (ord == n)
284303
implicit match {
285-
case m: Mirror.Product[`alt` & T] =>
304+
case m: Mirror.ProductOf[`alt` & T] =>
286305
unpickleCase[`alt` & T, m.ElemTypes](buf, m)
287306
}
288307
else unpickleCases[T, alts1](n + 1)(buf, ord)
289308
case _: Unit =>
290309
throw new IndexOutOfBoundsException(s"unexpected ordinal number: $ord")
291310
}
292311

293-
inline def derived[T](implicit ev: Mirror[T]): Pickler[T] = new {
312+
inline def derived[T](implicit ev: MirrorOf[T]): Pickler[T] = new {
294313
def pickle(buf: mutable.ListBuffer[Int], x: T): Unit =
295314
inline ev match {
296-
case m: Mirror.Sum[T] =>
315+
case m: Mirror.SumOf[T] =>
297316
val ord = m.ordinal(x)
298317
buf += ord
299318
pickleCases[m.ElemTypes](0)(buf, x, ord)
300-
case m: Mirror.Product[T] =>
319+
case m: Mirror.ProductOf[T] =>
301320
pickleElems[m.ElemTypes](0)(buf, x)
302321
}
303322
def unpickle(buf: mutable.ListBuffer[Int]): T =
304323
inline ev match {
305-
case m: Mirror.Sum[T] =>
324+
case m: Mirror.SumOf[T] =>
306325
val ord = nextInt(buf)
307326
unpickleCases[T, m.ElemTypes](0)(buf, ord)
308-
case m: Mirror.Product[T] =>
327+
case m: Mirror.ProductOf[T] =>
309328
unpickleCase[T, m.ElemTypes](buf, m)
310329
}
311330
}
@@ -341,7 +360,7 @@ object Show {
341360
Nil
342361
}
343362

344-
inline def showCase(x: Any, m: Mirror.Product[_]): String = {
363+
inline def showCase(x: Any, m: Mirror.ProductOf[_]): String = {
345364
val label = constValue[m.CaseLabel]
346365
showElems[m.ElemTypes, m.ElemLabels](0)(x).mkString(s"$label(", ", ", ")")
347366
}
@@ -351,21 +370,21 @@ object Show {
351370
case _: (alt *: alts1) =>
352371
if (ord == n)
353372
implicit match {
354-
case m: Mirror.Product[`alt`] =>
373+
case m: Mirror.ProductOf[`alt`] =>
355374
showCase(x, m)
356375
}
357376
else showCases[alts1](n + 1)(x, ord)
358377
case _: Unit =>
359378
throw new MatchError(x)
360379
}
361380

362-
inline def derived[T](implicit ev: Mirror[T]): Show[T] = new {
381+
inline def derived[T](implicit ev: MirrorOf[T]): Show[T] = new {
363382
def show(x: T): String =
364383
inline ev match {
365-
case m: Mirror.Sum[T] =>
384+
case m: Mirror.SumOf[T] =>
366385
val ord = m.ordinal(x)
367386
showCases[m.ElemTypes](0)(x, ord)
368-
case m: Mirror.Product[T] =>
387+
case m: Mirror.ProductOf[T] =>
369388
showCase(x, m)
370389
}
371390
}

0 commit comments

Comments
 (0)