Skip to content

Commit c77fdcc

Browse files
committed
Special treatment for Singletons
1 parent 1a709f1 commit c77fdcc

File tree

2 files changed

+71
-43
lines changed

2 files changed

+71
-43
lines changed

tests/run/typeclass-derivation2d.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ListBuffer(0, 0, 11, 0, 22, 0, 33, 1, 0, 0, 11, 0, 22, 1, 1)
44
Cons(Cons(11,Cons(22,Cons(33,Nil))),Cons(Cons(11,Cons(22,Nil)),Nil))
55
ListBuffer(1, 2)
66
Pair(1,2)
7-
Cons(hd = 11, tl = Cons(hd = 22, tl = Cons(hd = 33, tl = Nil())))
8-
Cons(hd = Cons(hd = 11, tl = Cons(hd = 22, tl = Cons(hd = 33, tl = Nil()))), tl = Cons(hd = Cons(hd = 11, tl = Cons(hd = 22, tl = Nil())), tl = Nil()))
9-
Cons(hd = Left(x = 1), tl = Cons(hd = Right(x = Pair(x = 2, y = 3)), tl = Nil()))
10-
Cons(hd = Left(x = 1), tl = Cons(hd = Right(x = Pair(x = 2, y = 3)), tl = Nil()))
7+
Cons(hd = 11, tl = Cons(hd = 22, tl = Cons(hd = 33, tl = Nil)))
8+
Cons(hd = Cons(hd = 11, tl = Cons(hd = 22, tl = Cons(hd = 33, tl = Nil))), tl = Cons(hd = Cons(hd = 11, tl = Cons(hd = 22, tl = Nil)), tl = Nil))
9+
Cons(hd = Left(x = 1), tl = Cons(hd = Right(x = Pair(x = 2, y = 3)), tl = Nil))
10+
Cons(hd = Left(x = 1), tl = Cons(hd = Right(x = Pair(x = 2, y = 3)), tl = Nil))

tests/run/typeclass-derivation2d.scala

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,29 @@ 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 {
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
1523

1624
object Mirror {
1725

1826
/** The Mirror for a sum type */
19-
trait Sum[T] extends Mirror[T] { self =>
27+
trait Sum extends Mirror { self =>
2028

2129
type ElemTypes <: Tuple
2230

2331
/** 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
2533
}
2634

2735
/** The Mirror for a product type */
28-
trait Product[T] extends Mirror[T] {
36+
trait Product extends Mirror {
2937

3038
/** The types of the elements */
3139
type ElemTypes <: Tuple
@@ -37,7 +45,12 @@ object Deriving {
3745
type ElemLabels <: Tuple
3846

3947
/** 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
4154
}
4255
}
4356

@@ -61,37 +74,41 @@ import Deriving._
6174

6275
sealed trait Lst[+T] // derives Eq, Pickler, Show
6376

64-
object Lst extends Mirror.Sum[Lst[_]] {
77+
object Lst extends Mirror.Sum {
78+
type MonoType = Lst[_]
6579

6680
def ordinal(x: Lst[_]) = x match {
6781
case x: Cons[_] => 0
6882
case Nil => 1
6983
}
7084

71-
implicit def mirror[T]: Mirror.Sum[Lst[T]] {
85+
implicit def mirror[T]: Mirror.Sum {
86+
type MonoType = Lst[T]
7287
type ElemTypes = (Cons[T], Nil.type)
7388
} = this.asInstanceOf
7489

7590
case class Cons[T](hd: T, tl: Lst[T]) extends Lst[T]
7691

77-
object Cons extends Mirror.Product[Cons[_]] {
92+
object Cons extends Mirror.Product {
93+
type MonoType = Lst[_]
7894

7995
def apply[T](x: T, xs: Lst[T]): Lst[T] = new Cons(x, xs)
8096

8197
def fromProduct(p: Product): Cons[_] =
8298
new Cons(productElement[Any](p, 0), productElement[Lst[Any]](p, 1))
8399

84-
implicit def mirror[T]: Mirror.Product[Cons[T]] {
100+
implicit def mirror[T]: Mirror.Product {
101+
type MonoType = Cons[T]
85102
type ElemTypes = (T, Lst[T])
86103
type CaseLabel = "Cons"
87104
type ElemLabels = ("hd", "tl")
88105
} = this.asInstanceOf
89106
}
90107

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 {
93109

94-
implicit def mirror: Mirror.Product[Nil.type] {
110+
implicit def mirror: Mirror.Singleton {
111+
type MonoType = Nil.type
95112
type ElemTypes = Unit
96113
type CaseLabel = "Nil"
97114
type ElemLabels = Unit
@@ -108,12 +125,14 @@ object Lst extends Mirror.Sum[Lst[_]] {
108125

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

111-
object Pair extends Mirror.Product[Pair[_]] {
128+
object Pair extends Mirror.Product {
129+
type MonoType = Pair[_]
112130

113131
def fromProduct(p: Product): Pair[_] =
114132
Pair(productElement[Any](p, 0), productElement[Any](p, 1))
115133

116-
implicit def mirror[T]: Mirror.Product[Pair[T]] {
134+
implicit def mirror[T]: Mirror.Product {
135+
type MonoType = Pair[T]
117136
type ElemTypes = (T, T)
118137
type CaseLabel = "Pair"
119138
type ElemLabels = ("x", "y")
@@ -129,14 +148,16 @@ object Pair extends Mirror.Product[Pair[_]] {
129148

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

132-
object Either extends Mirror.Sum[Either[_, _]] {
151+
object Either extends Mirror.Sum {
152+
type MonoType = Either[_, _]
133153

134154
def ordinal(x: Either[_, _]) = x match {
135155
case x: Left[_] => 0
136156
case x: Right[_] => 1
137157
}
138158

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

@@ -148,18 +169,22 @@ object Either extends Mirror.Sum[Either[_, _]] {
148169
case class Left[L](elem: L) extends Either[L, Nothing]
149170
case class Right[R](elem: R) extends Either[Nothing, R]
150171

151-
object Left extends Mirror.Product[Left[_]] {
172+
object Left extends Mirror.Product {
173+
type MonoType = Left[_]
152174
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]
154177
type ElemTypes = L *: Unit
155178
type CaseLabel = "Left"
156179
type ElemLabels = "x" *: Unit
157180
} = this.asInstanceOf
158181
}
159182

160-
object Right extends Mirror.Product[Right[_]] {
183+
object Right extends Mirror.Product {
184+
type MonoType = Right[_]
161185
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]
163188
type ElemTypes = R *: Unit
164189
type CaseLabel = "Right"
165190
type ElemLabels = "x" *: Unit
@@ -188,28 +213,28 @@ object Eq {
188213
true
189214
}
190215

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

194219
inline def eqlCases[Alts](n: Int)(x: Any, y: Any, ord: Int): Boolean =
195220
inline erasedValue[Alts] match {
196221
case _: (alt *: alts1) =>
197222
if (ord == n)
198223
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)
200225
}
201226
else eqlCases[alts1](n + 1)(x, y, ord)
202227
case _: Unit =>
203228
false
204229
}
205230

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] {
207232
def eql(x: T, y: T): Boolean =
208233
inline ev match {
209-
case m: Mirror.Sum[T] =>
234+
case m: SumMirrorOf[T] =>
210235
val ord = m.ordinal(x)
211236
ord == m.ordinal(y) && eqlCases[m.ElemTypes](0)(x, y, ord)
212-
case m: Mirror.Product[T] =>
237+
case m: ProductMirrorOf[T] =>
213238
eqlElems[m.ElemTypes](0)(x, y)
214239
}
215240
}
@@ -248,7 +273,7 @@ object Pickler {
248273
case _: (alt *: alts1) =>
249274
if (ord == n)
250275
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)
252277
}
253278
else pickleCases[alts1](n + 1)(buf, x, ord)
254279
case _: Unit =>
@@ -266,7 +291,7 @@ object Pickler {
266291
case _: Unit =>
267292
}
268293

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 = {
270295
inline val size = constValue[Tuple.Size[Elems]]
271296
inline if (size == 0)
272297
m.fromProduct(EmptyProduct)
@@ -282,30 +307,30 @@ object Pickler {
282307
case _: (alt *: alts1) =>
283308
if (ord == n)
284309
implicit match {
285-
case m: Mirror.Product[`alt` & T] =>
310+
case m: ProductMirrorOf[`alt` & T] =>
286311
unpickleCase[`alt` & T, m.ElemTypes](buf, m)
287312
}
288313
else unpickleCases[T, alts1](n + 1)(buf, ord)
289314
case _: Unit =>
290315
throw new IndexOutOfBoundsException(s"unexpected ordinal number: $ord")
291316
}
292317

293-
inline def derived[T](implicit ev: Mirror[T]): Pickler[T] = new {
318+
inline def derived[T](implicit ev: MirrorOf[T]): Pickler[T] = new {
294319
def pickle(buf: mutable.ListBuffer[Int], x: T): Unit =
295320
inline ev match {
296-
case m: Mirror.Sum[T] =>
321+
case m: SumMirrorOf[T] =>
297322
val ord = m.ordinal(x)
298323
buf += ord
299324
pickleCases[m.ElemTypes](0)(buf, x, ord)
300-
case m: Mirror.Product[T] =>
325+
case m: ProductMirrorOf[T] =>
301326
pickleElems[m.ElemTypes](0)(buf, x)
302327
}
303328
def unpickle(buf: mutable.ListBuffer[Int]): T =
304329
inline ev match {
305-
case m: Mirror.Sum[T] =>
330+
case m: SumMirrorOf[T] =>
306331
val ord = nextInt(buf)
307332
unpickleCases[T, m.ElemTypes](0)(buf, ord)
308-
case m: Mirror.Product[T] =>
333+
case m: ProductMirrorOf[T] =>
309334
unpickleCase[T, m.ElemTypes](buf, m)
310335
}
311336
}
@@ -341,31 +366,34 @@ object Show {
341366
Nil
342367
}
343368

344-
inline def showCase(x: Any, m: Mirror.Product[_]): String = {
369+
inline def showCase(x: Any, m: ProductMirrorOf[_]): String = {
345370
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+
}
347375
}
348376

349377
inline def showCases[Alts <: Tuple](n: Int)(x: Any, ord: Int): String =
350378
inline erasedValue[Alts] match {
351379
case _: (alt *: alts1) =>
352380
if (ord == n)
353381
implicit match {
354-
case m: Mirror.Product[`alt`] =>
382+
case m: ProductMirrorOf[`alt`] =>
355383
showCase(x, m)
356384
}
357385
else showCases[alts1](n + 1)(x, ord)
358386
case _: Unit =>
359387
throw new MatchError(x)
360388
}
361389

362-
inline def derived[T](implicit ev: Mirror[T]): Show[T] = new {
390+
inline def derived[T](implicit ev: MirrorOf[T]): Show[T] = new {
363391
def show(x: T): String =
364392
inline ev match {
365-
case m: Mirror.Sum[T] =>
393+
case m: SumMirrorOf[T] =>
366394
val ord = m.ordinal(x)
367395
showCases[m.ElemTypes](0)(x, ord)
368-
case m: Mirror.Product[T] =>
396+
case m: ProductMirrorOf[T] =>
369397
showCase(x, m)
370398
}
371399
}

0 commit comments

Comments
 (0)