Skip to content

Instantly share code, notes, and snippets.

@larsrh
Last active February 13, 2018 01:59
Show Gist options
  • Save larsrh/18cfc58e462ca01ba8fee1f5197a6d50 to your computer and use it in GitHub Desktop.
Save larsrh/18cfc58e462ca01ba8fee1f5197a6d50 to your computer and use it in GitHub Desktop.
Summon a conditional implicit
/*
* implicit conversion ("view"): implicit def f(x: A): B
* non-view implicit: implicit def f(implicit x: A): B
*
* we can summon implicit conversions with `implicitly[A => B]`
* we can't do that with non-view implicits
* this macro provides the trait `Conditional[A, B]` that provides precisely that
*/
package conditional
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
trait Conditional[A, B] {
def apply(a: A): B
}
object Conditional {
def impl[A : c.WeakTypeTag, B : c.WeakTypeTag](c: Context) = {
import c.universe._
val a = weakTypeOf[A]
val b = weakTypeOf[B]
val tree = q"""
new _root_.conditional.Conditional[$a, $b] {
def apply(a: $a): $b = {
implicit val _a: $a = a
_root_.scala.Predef.implicitly[$b]
}
}
"""
c.Expr[Conditional[A, B]](tree)
}
implicit def summon[A, B]: Conditional[A, B] = macro impl[A, B]
}
@propensive
Copy link

You should use c.freshName to generate identifiers for a and _a in case these might shadow (badly named!) implicits you want implicitly to find.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment