@@ -46,17 +46,17 @@ given derived[T: Type](using Quotes): Expr[Eq[T]] =
46
46
val ev : Expr [Mirror .Of [T ]] = Expr .summon[Mirror .Of [T ]].get
47
47
48
48
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 )}) }
60
60
61
61
// case for Mirror.ProductOf[T]
62
62
// ...
@@ -78,19 +78,19 @@ Instead we extract the tuple-type for element types using pattern matching over
78
78
quotes and more specifically of the refined type:
79
79
80
80
``` scala
81
- case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} => ...
81
+ case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = elementTypes }} => ...
82
82
```
83
83
84
84
Shown below is the implementation of ` summonAll ` as a macro. We assume that
85
85
given instances for our primitive types exist.
86
86
87
87
``` 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
94
94
```
95
95
96
96
One 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
101
101
check we want to generate is the following:
102
102
103
103
``` 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 ))
107
107
```
108
108
109
109
### Calling the derived method inside the macro
@@ -159,39 +159,39 @@ object Eq:
159
159
160
160
def summonAll [T : Type ](using Quotes ): List [Expr [Eq [_]]] =
161
161
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
166
166
167
167
given derived [T : Type ](using q : Quotes ): Expr [Eq [T ]] =
168
168
import quotes .reflect ._
169
169
170
170
val ev : Expr [Mirror .Of [T ]] = Expr .summon[Mirror .Of [T ]].get
171
171
172
172
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 )}) }
195
195
end derived
196
196
end Eq
197
197
0 commit comments