Last active
April 10, 2019 18:07
-
-
Save b-studios/4f1ca0356fbcd2ad8470a981ec70f2d6 to your computer and use it in GitHub Desktop.
Bad interaction of type matcher and meta programming?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package examples | |
import scala.quoted._ | |
object bug extends App { | |
val toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader) | |
implied for scala.quoted.Toolbox = toolbox | |
sealed trait HList | |
sealed trait HNil extends HList | |
sealed trait ::[E, T <: HList] extends HList | |
type STM[A, L <: HList] = L match { | |
case HNil => Expr[A] | |
case e :: rs => (Expr[A] => STM[e, rs]) => STM[e, rs] | |
} | |
type Stm[A, L <: HList] = L match { | |
case HNil => A | |
case e :: rs => (A => Stm[e, rs]) => Stm[e, rs] | |
} | |
trait Effects[L <: HList] { | |
def reify[A] given Type[A]: STM[A, L] => Expr[Stm[A, L]] | |
def reflect[A] given Type[A]: Expr[Stm[A, L]] => STM[A, L] | |
} | |
implied empty for Effects[HNil] { | |
def reify[A] given Type[A] = m => m | |
def reflect[A] given Type[A] = m => m | |
} | |
// for reify, we need type tags for E and also strangely for L. | |
implied cons [E, L <: HList] given Effects[L] given Type[E] given Type[L] for Effects[E :: L] { | |
def reify[A] given Type[A] = m => '{ k => ${ Effects[L].reify[E] { m( a => Effects[L].reflect[E]('k(a))) } }} | |
def reflect[A] given Type[A] = m => k => Effects[L].reflect[E] { m('{ a => ${ Effects[L].reify[E]( k('a)) } })} | |
} | |
def Effects[L <: HList] given Effects[L]: Effects[L] = the[Effects[L]] | |
type RS = Boolean :: RS2 | |
type RS2 = Int :: String :: HNil | |
val m: STM[Int, RS] = k => k('{42}) | |
// compiles, but results in a runtime error: | |
// println(Effects[RS].reify[Int] { m }.show) | |
// | |
// the implicit search results in the following value: | |
// val effects = cons[Boolean, RS2] given (cons[Int, String :: HNil] given (cons[String, HNil] given empty)) | |
// | |
// so the above is equivalent to: | |
// println(effects.reify[Int] { m }.show) | |
// | |
// error: | |
// 37 | def reify[A] given Type[A] = m => '{ k => ${ Effects[L].reify[E] { m( a => Effects[L].reflect[E]('k(a))) } }} | |
// | ^ | |
// | value apply is not a member of R | |
// | This location is in code that was inlined at Bug.scala:37 | |
// manually inlining reify works | |
// val res : Expr[Stm[Int, RS]] = '{ k => ${ Effects[RS2].reify[Boolean] { m(a => Effects[RS2].reflect[Boolean]('k(a))) }}} | |
// println(res.show) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment