We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hi! I was trying to learn how to derive typeclass instances with macros but the code from How to write a type class derived method using macros does not compile with 3.0.0-M1.
derived
import scala.deriving._ import scala.quoted._ import scala.quoted.matching._ trait Eq[T] { def eqv(x: T, y: T): Boolean } object Eq { given Eq[String] { def eqv(x: String, y: String) = x == y } given Eq[Int] { def eqv(x: Int, y: Int) = x == y } def eqProduct[T](body: (T, T) => Boolean): Eq[T] = new Eq[T] { def eqv(x: T, y: T): Boolean = body(x, y) } def eqSum[T](body: (T, T) => Boolean): Eq[T] = new Eq[T] { def eqv(x: T, y: T): Boolean = body(x, y) } def summonAll[T](t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { case '[String *: $tpes] => '{ summon[Eq[String]] } :: summonAll(tpes) case '[Int *: $tpes] => '{ summon[Eq[Int]] } :: summonAll(tpes) case '[$tpe *: $tpes] => derived(using tpe, qctx) :: summonAll(tpes) case '[EmptyTuple] => Nil } given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = { import qctx.reflect._ val ev: Expr[Mirror.Of[T]] = Expr.summon(using '[Mirror.Of[T]]).get ev match { case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = $elementTypes }} => val elemInstances = summonAll(elementTypes) val eqProductBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => { elemInstances.zipWithIndex.foldLeft(Expr(true: Boolean)) { case (acc, (elem, index)) => val e1 = '{$x.asInstanceOf[Product].productElement(${Expr(index)})} val e2 = '{$y.asInstanceOf[Product].productElement(${Expr(index)})} '{ $acc && $elem.asInstanceOf[Eq[Any]].eqv($e1, $e2) } } } '{ eqProduct((x: T, y: T) => ${eqProductBody('x, 'y)}) } case '{ $m: Mirror.SumOf[T] { type MirroredElemTypes = $elementTypes }} => val elemInstances = summonAll(elementTypes) val eqSumBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => { val ordx = '{ $m.ordinal($x) } val ordy = '{ $m.ordinal($y) } val elements = Expr.ofList(elemInstances) '{ $ordx == $ordy && $elements($ordx).asInstanceOf[Eq[Any]].eqv($x, $y) } } '{ eqSum((x: T, y: T) => ${eqSumBody('x, 'y)}) } } } } object Macro3 { extension [T](x: =>T) inline def === (y: =>T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) implicit inline def eqGen[T]: Eq[T] = ${ Eq.derived[T] } }
[error] -- [E006] Not Found Error: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:29:71 [error] 29 | case '[String *: $tpes] => '{ summon[Eq[String]] } :: summonAll(tpes) [error] | ^^^^ [error] | Not found: tpes [error] -- [E006] Not Found Error: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:30:71 [error] 30 | case '[Int *: $tpes] => '{ summon[Eq[Int]] } :: summonAll(tpes) [error] | ^^^^ [error] | Not found: tpes [error] -- [E006] Not Found Error: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:31:71 [error] 31 | case '[$tpe *: $tpes] => derived(using tpe, qctx) :: summonAll(tpes) [error] | ^^^^ [error] | Not found: tpes [error] -- [E006] Not Found Error: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:31:47 [error] 31 | case '[$tpe *: $tpes] => derived(using tpe, qctx) :: summonAll(tpes) [error] | ^^^ [error] | Not found: tpe [warn] -- Warning: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:38:53 [warn] 38 | val ev: Expr[Mirror.Of[T]] = Expr.summon(using '[Mirror.Of[T]]).get [warn] | ^^^^^^^^^^^^^^^ [warn] |Consider using canonical type constructor scala.quoted.Type[Mirror.Of[T]] instead [error] -- [E006] Not Found Error: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:42:40 [error] 42 | val elemInstances = summonAll(elementTypes) [error] | ^^^^^^^^^^^^ [error] | Not found: elementTypes [error] -- [E006] Not Found Error: /Users/pierre/GIT/dotty-example-project/src/main/scala/Test.scala:57:40 [error] 57 | val elemInstances = summonAll(elementTypes) [error] | ^^^^^^^^^^^^ [error] | Not found: elementTypes [warn] one warning found [error] 6 errors found
The text was updated successfully, but these errors were encountered:
There's an up-to-date example in our testsuite, https://github.com/lampepfl/dotty/blob/master/tests/run-macros/i8007/Macro_3.scala, though the syntax has already changed compared to 3.0.0-M1, so if you're using that we need to go back in the history a bit: https://github.com/lampepfl/dotty/blob/3.0.0-M1/tests/run-macros/i8007/Macro_3.scala
Sorry, something went wrong.
So, PR welcome to copy-paste https://github.com/lampepfl/dotty/blob/master/tests/run-macros/i8007/Macro_3.scala into the docs in place of the version that is there now.
@smarter Thanks! Submitted a PR.
Successfully merging a pull request may close this issue.
Hi! I was trying to learn how to derive typeclass instances with macros but the code from How to write a type class
derived
method using macros does not compile with 3.0.0-M1.Minimized example
Output
The text was updated successfully, but these errors were encountered: