Skip to content

Instantly share code, notes, and snippets.

@yilinwei
Last active May 16, 2017 17:03
Show Gist options
  • Save yilinwei/ce7704550fe9db84b94deeb3a46604ee to your computer and use it in GitHub Desktop.
Save yilinwei/ce7704550fe9db84b94deeb3a46604ee to your computer and use it in GitHub Desktop.
CanResolveMacro
package cats
package macros
import reflect.macros.Context
trait ImplicitResolutionSpec {
def canResolve[A, F[_]](imports: Unit): F[A] = macro CanResolveMacro.mkImplicitlyBlock[A, F]
def canResolveK[G[_], F[_[_]]](imports: Unit): F[G] = macro CanResolveMacroK.mkImplicitlyBlock[G, F]
}
object CanResolveMacro {
val filterClasses = Set(
"scala.Serializable",
"java.io.Serializable",
"java.lang.Object",
"scala.Any"
)
}
import CanResolveMacro._
final class CanResolveMacro(val c: Context) {
import c.universe._
def mkImplicitlyBlock[A, F[_]](imports: c.Expr[Unit])(
implicit wtf: c.WeakTypeTag[F[_]], wta: c.WeakTypeTag[A]): c.Expr[F[A]] = {
val resolve = wtf.tpe.baseClasses.filterNot(cls => filterClasses.contains(cls.fullName)).map(sym => q"implicitly[$sym[$wta]]")
val expr = c.Expr[F[A]](q"""
{
..$imports
..${resolve.reverse}
}
""")
expr
}
}
final class CanResolveMacroK(val c: Context) {
import c.universe._
def mkImplicitlyBlock[G[_], F[_[_]]](imports: c.Expr[Unit])(
implicit wtf: c.WeakTypeTag[F[G]], wta: c.WeakTypeTag[G[_]]): c.Expr[F[G]] = {
val curried: List[Type] = wtf.tpe match {
case p: PolyType => p.resultType.typeArgs.tail
case _ => List.empty
}
val resolve = wtf
.tpe
.baseClasses
.filterNot(cls => filterClasses.contains(cls.fullName))
.map {
case sym: TypeSymbol =>
if(sym.typeParams.size == 1)
q"implicitly[$sym[$wta]]"
else {
q"implicitly[$sym[..${wta.tpe :: curried}]]"
}
}
val expr = c.Expr[F[G]](q"""
{
..$imports
..${resolve.reverse}
}
""")
expr
}
}
package cats
import cats.macros.ImplicitResolutionSpec
import cats.functor._
final class ImplicitResolutionTests extends ImplicitResolutionSpec {
canResolve[String, Monoid] {
import cats.implicits._
}
canResolveK[Order, Contravariant] {
import cats.implicits._
}
canResolveK[Order, Contravariant] {
import cats.instances.order._
}
canResolveK[Option, MonadError[?[_], Unit]] {
import cats.implicits._
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment