Created
May 29, 2018 10:13
-
-
Save milessabin/c79adebd879a3b0cc79a12e3523e49aa to your computer and use it in GitHub Desktop.
Using type level continuation passing style to rewrite a whitebox macro (which relies on fundep materialization) as a blackbox macro
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
import scala.language.higherKinds | |
// Whitebox ... | |
trait Schema[T, R] { | |
def conv(t: T): R | |
} | |
object Schema { | |
// Whitebox macro: R is computed from T | |
implicit def mkSchema[T, R]: Schema[T, R] = ??? // macro ... | |
} | |
trait UseComputed[A] { | |
def run(a: A): Int | |
} | |
object UseComputed { | |
implicit def mkUse[A]: UseComputed[A] = ??? | |
} | |
object Test { | |
// R is bound by Schema[T, R] ... a ban on whitebox macros would prevent this | |
def foo[T, R](t: T)(implicit str: Schema[T, R], usr: UseComputed[R]): Int = | |
usr.run(str.conv(t)) | |
} | |
// Blackbox via type level CPS conversion ... | |
trait SchemaCPS[T, Cont[_]] { | |
type R | |
def conv(t: T): R | |
val contR: Cont[R] | |
} | |
object SchemaCPS { | |
implicit def mkSchemaCPS[T, F[_]]: SchemaCPS[T, F] = ??? // macro ... | |
// Example expansion of macro | |
class SchemaUseComputed[T] extends SchemaCPS[T, UseComputed] { | |
type R = Option[T] // arbitrary computed type | |
def conv(t: T): R = Some(t) | |
val contR = implicitly[UseComputed[R]] // continuation materialized in macro expansion | |
} | |
} | |
object TestCPS { | |
// Note that R is abstract and never escapes ... this is blackbox | |
def foo[T](t: T)(implicit suc: SchemaCPS[T, UseComputed]): Int = { | |
import suc._ | |
contR.run(conv(t)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment