@@ -46,17 +46,17 @@ given derived[T: Type](using Quotes): Expr[Eq[T]] =
4646 val ev : Expr [Mirror .Of [T ]] = Expr .summon[Mirror .Of [T ]].get
4747
4848 ev match
49- case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} =>
50- val elemInstances = summonAll[elementTypes]
51- val eqProductBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) =>
52- elemInstances.zipWithIndex.foldLeft(Expr (true : Boolean )) {
53- case (acc, (elem, index)) =>
54- val e1 = ' {$x.asInstanceOf [Product ].productElement($ {Expr (index)})}
55- val e2 = ' {$y.asInstanceOf [Product ].productElement($ {Expr (index)})}
56- ' { $acc && $elem.asInstanceOf [Eq [Any ]].eqv($e1, $e2) }
57- }
58-
59- ' { eqProduct((x : T , y : T ) => $ {eqProductBody(' x , ' y )}) }
49+ case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} =>
50+ val elemInstances = summonAll[elementTypes]
51+ val eqProductBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) =>
52+ elemInstances.zipWithIndex.foldLeft(Expr (true : Boolean )) {
53+ case (acc, (elem, index)) =>
54+ val e1 = ' {$x.asInstanceOf [Product ].productElement($ {Expr (index)})}
55+ val e2 = ' {$y.asInstanceOf [Product ].productElement($ {Expr (index)})}
56+ ' { $acc && $elem.asInstanceOf [Eq [Any ]].eqv($e1, $e2) }
57+ }
58+
59+ ' { eqProduct((x : T , y : T ) => $ {eqProductBody(' x , ' y )}) }
6060
6161 // case for Mirror.ProductOf[T]
6262 // ...
@@ -78,19 +78,19 @@ Instead we extract the tuple-type for element types using pattern matching over
7878quotes and more specifically of the refined type:
7979
8080``` scala
81- case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} => ...
81+ case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} => ...
8282```
8383
8484Shown below is the implementation of ` summonAll ` as a macro. We assume that
8585given instances for our primitive types exist.
8686
8787``` scala
88- def summonAll [T : Type ](using Quotes ): List [Expr [Eq [_]]] =
89- Type .of[T ] match
90- case ' [String *: tpes] => ' { summon[Eq [String ]] } :: summonAll[tpes]
91- case ' [Int *: tpes] => ' { summon[Eq [Int ]] } :: summonAll[tpes]
92- case ' [tpe *: tpes] => derived[tpe] :: summonAll[tpes]
93- case ' [EmptyTuple ] => Nil
88+ def summonAll [T : Type ](using Quotes ): List [Expr [Eq [_]]] =
89+ Type .of[T ] match
90+ case ' [String *: tpes] => ' { summon[Eq [String ]] } :: summonAll[tpes]
91+ case ' [Int *: tpes] => ' { summon[Eq [Int ]] } :: summonAll[tpes]
92+ case ' [tpe *: tpes] => derived[tpe] :: summonAll[tpes]
93+ case ' [EmptyTuple ] => Nil
9494```
9595
9696One additional difference with the body of ` derived ` here as opposed to the one
@@ -101,9 +101,9 @@ class that holds a name of type `String` and an age of type `Int`, the equality
101101check we want to generate is the following:
102102
103103``` scala
104- true
105- && Eq [String ].eqv(x.productElement(0 ),y.productElement(0 ))
106- && Eq [Int ].eqv(x.productElement(1 ), y.productElement(1 ))
104+ true
105+ && Eq [String ].eqv(x.productElement(0 ),y.productElement(0 ))
106+ && Eq [Int ].eqv(x.productElement(1 ), y.productElement(1 ))
107107```
108108
109109### Calling the derived method inside the macro
@@ -159,39 +159,39 @@ object Eq:
159159
160160 def summonAll [T : Type ](using Quotes ): List [Expr [Eq [_]]] =
161161 Type .of[T ] match
162- case ' [String *: tpes] => ' { summon[Eq [String ]] } :: summonAll[tpes]
163- case ' [Int *: tpes] => ' { summon[Eq [Int ]] } :: summonAll[tpes]
164- case ' [tpe *: tpes] => derived[tpe] :: summonAll[tpes]
165- case ' [EmptyTuple ] => Nil
162+ case ' [String *: tpes] => ' { summon[Eq [String ]] } :: summonAll[tpes]
163+ case ' [Int *: tpes] => ' { summon[Eq [Int ]] } :: summonAll[tpes]
164+ case ' [tpe *: tpes] => derived[tpe] :: summonAll[tpes]
165+ case ' [EmptyTuple ] => Nil
166166
167167 given derived [T : Type ](using q : Quotes ): Expr [Eq [T ]] =
168168 import quotes .reflect ._
169169
170170 val ev : Expr [Mirror .Of [T ]] = Expr .summon[Mirror .Of [T ]].get
171171
172172 ev match
173- case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} =>
174- val elemInstances = summonAll[elementTypes]
175- val eqProductBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) =>
176- elemInstances.zipWithIndex.foldLeft(Expr (true : Boolean )) {
177- case (acc, (elem, index)) =>
178- val e1 = ' {$x.asInstanceOf [Product ].productElement($ {Expr (index)})}
179- val e2 = ' {$y.asInstanceOf [Product ].productElement($ {Expr (index)})}
180-
181- ' { $acc && $elem.asInstanceOf [Eq [Any ]].eqv($e1, $e2) }
182- }
183- ' { eqProduct((x : T , y : T ) => $ {eqProductBody(' x , ' y )}) }
184-
185- case ' { $m : Mirror .SumOf [T ] { type MirroredElemTypes = elementTypes }} =>
186- val elemInstances = summonAll[elementTypes]
187- val eqSumBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) =>
188- val ordx = ' { $m.ordinal($x) }
189- val ordy = ' { $m.ordinal($y) }
190-
191- val elements = Expr .ofList(elemInstances)
192- ' { $ordx == $ordy && $elements($ordx).asInstanceOf [Eq [Any ]].eqv($x, $y) }
193-
194- ' { eqSum((x : T , y : T ) => $ {eqSumBody(' x , ' y )}) }
173+ case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} =>
174+ val elemInstances = summonAll[elementTypes]
175+ val eqProductBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) =>
176+ elemInstances.zipWithIndex.foldLeft(Expr (true : Boolean )) {
177+ case (acc, (elem, index)) =>
178+ val e1 = ' {$x.asInstanceOf [Product ].productElement($ {Expr (index)})}
179+ val e2 = ' {$y.asInstanceOf [Product ].productElement($ {Expr (index)})}
180+
181+ ' { $acc && $elem.asInstanceOf [Eq [Any ]].eqv($e1, $e2) }
182+ }
183+ ' { eqProduct((x : T , y : T ) => $ {eqProductBody(' x , ' y )}) }
184+
185+ case ' { $m : Mirror .SumOf [T ] { type MirroredElemTypes = elementTypes }} =>
186+ val elemInstances = summonAll[elementTypes]
187+ val eqSumBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) =>
188+ val ordx = ' { $m.ordinal($x) }
189+ val ordy = ' { $m.ordinal($y) }
190+
191+ val elements = Expr .ofList(elemInstances)
192+ ' { $ordx == $ordy && $elements($ordx).asInstanceOf [Eq [Any ]].eqv($x, $y) }
193+
194+ ' { eqSum((x : T , y : T ) => $ {eqSumBody(' x , ' y )}) }
195195 end derived
196196end Eq
197197
0 commit comments