scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

Poly functions are not beta reduced

Open Katrix opened this issue 3 years ago • 4 comments

Compiler version

3.2.0

Minimized code

//file a.scala
object betaReduceTest {

  inline def macroPolyFun[A](inline arg: A, inline f: [Z] => Z => String): String =
    ${ macroPolyFunImpl[A]('arg, 'f) }

  def macroPolyFunImpl[A: Type](arg: Expr[A], f: Expr[[Z] => Z => String])(using Quotes): Expr[String] =
    Expr.betaReduce('{ $f($arg) })

  inline def macroFun[A](inline arg: A, inline f: A => String): String =
    ${ macroFunImpl[A]('arg, 'f) }

  def macroFunImpl[A: Type](arg: Expr[A], f: Expr[A => String])(using Quotes): Expr[String] =
    Expr.betaReduce('{ $f($arg) })
}

//file b.scala
object betaReduceTest2 {

  def test: Unit = {
    betaReduceTest.macroPolyFun("foo", [Z] => (arg: Z) => arg.toString)
    betaReduceTest.macroFun("foo", arg => arg.toString)
  }
}

Decompiled code (with Fernflower)

   public void test() {
      String var10000 = (String)((Function1)(new 1())).apply("foo");
      "foo".toString();
   }

Expectation

That both the normal and poly function both beta reduce

Katrix avatar Sep 04 '22 17:09 Katrix

You mean, the reducer should do type inference on the argument? That would be a lot to ask!

odersky avatar Sep 05 '22 07:09 odersky

Not sure I understand. Are you saying it does work in some cases already, and I just did it wrong?

Katrix avatar Sep 05 '22 18:09 Katrix

No, not at all. Just that it would be a rather big jump from what we have to this, and something that would tear down some important modularity barriers we have in the implementation.

odersky avatar Sep 05 '22 19:09 odersky

Managed to work around this for now using value classes and dependent function types instead of poly times. Seems these beta reduce just fine.

Katrix avatar Sep 06 '22 21:09 Katrix