Skip to content

Commit 5ff60af

Browse files
committed
Shaped -> Generic
Go to a system where Generic contains the Shape as a member instead of having it as a parameter. This makes Generic searchable with an implicit without having to know its shape.
1 parent 69294d9 commit 5ff60af

File tree

1 file changed

+42
-45
lines changed

1 file changed

+42
-45
lines changed

tests/run/typeclass-derivation2a.scala

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,6 @@ object TypeLevel {
8080
def elementLabel(n: Int) = reflected.label(ordinal)(n + 1)
8181
}
8282

83-
/** A class for mapping between an ADT value and
84-
* the case mirror that represents the value.
85-
*/
86-
abstract class Reflected[T] {
87-
88-
/** The case mirror corresponding to ADT instance `x` */
89-
def reflect(x: T): Mirror
90-
91-
/** The ADT instance corresponding to given `mirror` */
92-
def reify(mirror: Mirror): T
93-
94-
/** The companion object of the ADT */
95-
def common: ReflectedClass
96-
}
97-
9883
/** The shape of an ADT.
9984
* This is eithe a product (`Case`) or a sum (`Cases`) of products.
10085
*/
@@ -110,7 +95,20 @@ object TypeLevel {
11095
/** Every generic derivation starts with a typeclass instance of this type.
11196
* It informs that type `T` has shape `S` and also implements runtime reflection on `T`.
11297
*/
113-
abstract class Shaped[T, S <: Shape] extends Reflected[T]
98+
abstract class Generic[T] {
99+
100+
/** The shape of the `T` */
101+
type Shape <: TypeLevel.Shape
102+
103+
/** The case mirror corresponding to ADT instance `x` */
104+
def reflect(x: T): Mirror
105+
106+
/** The ADT instance corresponding to given `mirror` */
107+
def reify(mirror: Mirror): T
108+
109+
/** The companion object of the ADT */
110+
def common: ReflectedClass
111+
}
114112
}
115113

116114
// An algebraic datatype
@@ -123,17 +121,14 @@ object Lst {
123121
// common compiler-generated infrastructure
124122
import TypeLevel._
125123

126-
type Shape[T] = Shape.Cases[(
127-
Shape.Case[Cons[T], (T, Lst[T])],
128-
Shape.Case[Nil.type, Unit]
129-
)]
130-
131124
val reflectedClass = new ReflectedClass("Cons\000hd\000tl\001Nil")
132125
import reflectedClass.mirror
133126

134-
val NilMirror = mirror(1)
135-
136-
implicit def derived$Shaped[T]: Shaped[Lst[T], Shape[T]] = new {
127+
class GenericLst[T] extends Generic[Lst[T]] {
128+
type Shape = Shape.Cases[(
129+
Shape.Case[Cons[T], (T, Lst[T])],
130+
Shape.Case[Nil.type, Unit]
131+
)]
137132
def reflect(xs: Lst[T]): Mirror = xs match {
138133
case xs: Cons[T] => mirror(0, xs)
139134
case Nil => mirror(1)
@@ -144,6 +139,7 @@ object Lst {
144139
}
145140
def common = reflectedClass
146141
}
142+
implicit def GenericLst[T]: GenericLst[T] = new GenericLst[T]
147143

148144
// three clauses that could be generated from a `derives` clause
149145
implicit def derived$Eq[T: Eq]: Eq[Lst[T]] = Eq.derived
@@ -158,18 +154,19 @@ object Pair {
158154
// common compiler-generated infrastructure
159155
import TypeLevel._
160156

161-
type Shape[T] = Shape.Case[Pair[T], (T, T)]
162-
163157
val reflectedClass = new ReflectedClass("Pair\000x\000y")
164158
import reflectedClass.mirror
165159

166-
implicit def derived$Shape[T]: Shaped[Pair[T], Shape[T]] = new {
160+
class GenericPair[T] extends Generic[Pair[T]] {
161+
type Shape = Shape.Case[Pair[T], (T, T)]
162+
167163
def reflect(xy: Pair[T]) =
168164
mirror(0, xy)
169165
def reify(c: Mirror): Pair[T] =
170166
Pair(c(0).asInstanceOf, c(1).asInstanceOf)
171167
def common = reflectedClass
172168
}
169+
implicit def GenericPair[T]: GenericPair[T] = new GenericPair[T]
173170

174171
// clauses that could be generated from a `derives` clause
175172
implicit def derived$Eq[T: Eq]: Eq[Pair[T]] = Eq.derived
@@ -184,15 +181,14 @@ case class Right[R](x: R) extends Either[Nothing, R]
184181
object Either {
185182
import TypeLevel._
186183

187-
type Shape[L, R] = Shape.Cases[(
188-
Shape.Case[Left[L], L *: Unit],
189-
Shape.Case[Right[R], R *: Unit]
190-
)]
191-
192184
val reflectedClass = new ReflectedClass("Left\000x\001Right\000x")
193185
import reflectedClass.mirror
194186

195-
implicit def derived$Shape[L, R]: Shaped[Either[L, R], Shape[L, R]] = new {
187+
class GenericEither[L, R] extends Generic[Either[L, R]] {
188+
type Shape = Shape.Cases[(
189+
Shape.Case[Left[L], L *: Unit],
190+
Shape.Case[Right[R], R *: Unit]
191+
)]
196192
def reflect(e: Either[L, R]): Mirror = e match {
197193
case e: Left[L] => mirror(0, e)
198194
case e: Right[R] => mirror(1, e)
@@ -203,6 +199,7 @@ object Either {
203199
}
204200
def common = reflectedClass
205201
}
202+
implicit def GenericEither[L, R]: GenericEither[L, R] = new GenericEither[L, R]
206203

207204
implicit def derived$Eq[L: Eq, R: Eq]: Eq[Either[L, R]] = Eq.derived
208205
implicit def derived$Pickler[L: Pickler, R: Pickler]: Pickler[Either[L, R]] = Pickler.derived
@@ -240,11 +237,11 @@ object Eq {
240237
false
241238
}
242239

243-
inline def derived[T, S <: Shape](implicit ev: Shaped[T, S]): Eq[T] = new {
240+
inline def derived[T, S <: Shape](implicit ev: Generic[T]): Eq[T] = new {
244241
def eql(x: T, y: T): Boolean = {
245242
val xm = ev.reflect(x)
246243
val ym = ev.reflect(y)
247-
inline erasedValue[S] match {
244+
inline erasedValue[ev.Shape] match {
248245
case _: Shape.Cases[alts] =>
249246
xm.ordinal == ym.ordinal &&
250247
eqlCases[alts](xm, ym, 0)
@@ -303,18 +300,18 @@ object Pickler {
303300
case _: Unit =>
304301
}
305302

306-
inline def unpickleCase[T, Elems <: Tuple](r: Reflected[T], buf: mutable.ListBuffer[Int], ordinal: Int): T = {
303+
inline def unpickleCase[T, Elems <: Tuple](gen: Generic[T], buf: mutable.ListBuffer[Int], ordinal: Int): T = {
307304
inline val size = constValue[Tuple.Size[Elems]]
308305
inline if (size == 0)
309-
r.reify(r.common.mirror(ordinal))
306+
gen.reify(r.common.mirror(ordinal))
310307
else {
311308
val elems = new Array[Object](size)
312309
unpickleElems[Elems](buf, elems, 0)
313-
r.reify(r.common.mirror(ordinal, elems))
310+
gen.reify(r.common.mirror(ordinal, elems))
314311
}
315312
}
316313

317-
inline def unpickleCases[T, Alts <: Tuple](r: Reflected[T], buf: mutable.ListBuffer[Int], ordinal: Int, n: Int): T =
314+
inline def unpickleCases[T, Alts <: Tuple](r: Generic[T], buf: mutable.ListBuffer[Int], ordinal: Int, n: Int): T =
318315
inline erasedValue[Alts] match {
319316
case _: (Shape.Case[_, elems] *: alts1) =>
320317
if (n == ordinal) unpickleCase[T, elems](r, buf, ordinal)
@@ -323,18 +320,18 @@ object Pickler {
323320
throw new IndexOutOfBoundsException(s"unexpected ordinal number: $ordinal")
324321
}
325322

326-
inline def derived[T, S <: Shape](implicit ev: Shaped[T, S]): Pickler[T] = new {
323+
inline def derived[T, S <: Shape](implicit ev: Generic[T]): Pickler[T] = new {
327324
def pickle(buf: mutable.ListBuffer[Int], x: T): Unit = {
328325
val xm = ev.reflect(x)
329-
inline erasedValue[S] match {
326+
inline erasedValue[ev.Shape] match {
330327
case _: Shape.Cases[alts] =>
331328
buf += xm.ordinal
332329
pickleCases[alts](buf, xm, 0)
333330
case _: Shape.Case[_, elems] =>
334331
pickleElems[elems](buf, xm, 0)
335332
}
336333
}
337-
def unpickle(buf: mutable.ListBuffer[Int]): T = inline erasedValue[S] match {
334+
def unpickle(buf: mutable.ListBuffer[Int]): T = inline erasedValue[ev.Shape] match {
338335
case _: Shape.Cases[alts] =>
339336
unpickleCases[T, alts](ev, buf, nextInt(buf), 0)
340337
case _: Shape.Case[_, elems] =>
@@ -379,10 +376,10 @@ object Show {
379376
throw new MatchError(xm)
380377
}
381378

382-
inline def derived[T, S <: Shape](implicit ev: Shaped[T, S]): Show[T] = new {
379+
inline def derived[T, S <: Shape](implicit ev: Generic[T]): Show[T] = new {
383380
def show(x: T): String = {
384381
val xm = ev.reflect(x)
385-
val args = inline erasedValue[S] match {
382+
val args = inline erasedValue[ev.Shape] match {
386383
case _: Shape.Cases[alts] =>
387384
showCases[alts](xm, 0)
388385
case _: Shape.Case[_, elems] =>
@@ -473,4 +470,4 @@ object Test extends App {
473470
val zs1 = copy(zs)
474471
showPrintln(zs1)
475472
assert(eql(zs, zs1))
476-
}
473+
}

0 commit comments

Comments
 (0)