Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ariwaranosai/8250902e91e88ed206a83fdb7c5ee52c to your computer and use it in GitHub Desktop.
Save ariwaranosai/8250902e91e88ed206a83fdb7c5ee52c to your computer and use it in GitHub Desktop.
SI-2712 by the examples
import scalaz.{Monad}
import scalaz.OptionT
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz.std.scalaFuture._
import scala.language.existentials
import scala.language.experimental.macros
import scala.language.higherKinds
import scala.annotation.{ StaticAnnotation, tailrec }
import scala.reflect.api.Universe
import scala.reflect.macros.{ blackbox, whitebox }
trait P[I, A] {
def map[B](f: A => B): P[I, B] = new P[I, B] {}
def flatMap[B](f: A => P[I, B]): P[I, B] = new P[I, B] {}
}
object P {
implicit def pInstances[I] =
new Monad[({type λ[A] = P[I, A]})#λ] {
override def point[A](a: => A): P[I, A] = new P[I, A] {}
override def map[A, B](m: P[I, A])(f: A => B): P[I, B] = m.map(f)
override def bind[A, B](m: P[I, A])(f: A => P[I, B]): P[I, B] = m.flatMap(f)
}
}
type P2[A] = P[Int, A]
implicitly[Monad[P2]] // OK
implicitly[Monad[({type λ[A] = P[Int, A]})#λ]] // OK
// WITH HIGHER KINDED: implicits on Monad transformer
implicitly[Monad[({type λ[A] = OptionT[Future, A]})#λ]] // OK
// now using P, it needs to infer Monad[P2] or Monad[({type λ[A] = P[Int, A]})#λ )
// type lambda fails
implicitly[Monad[({type λ[A] = OptionT[({type λ[A] = P[Int, A]})#λ, A]})#λ]] // KO
optionTMonadPlus[({type λ[A] = P[Int, A]})#λ] // OK
// type alias fails too
implicitly[Monad[({type λ[A] = OptionT[P2, A]})#λ]] // KO
optionTMonadPlus[P2] // OK
// TYPE LAMBDA IN MACRO
// In a scala file
package test
trait Gen[F[_]]
object Gen {
def apply[F[_]](implicit gen: Gen[F]): Gen[F] = gen
implicit def materialize[F[_]]: Gen[F] =
macro GenMacros.materialize[F]
}
class GenMacros(val c: whitebox.Context) {
import c.universe._
def materialize[T[_]](implicit tTag: WeakTypeTag[T[_]]): Tree = {
val tpe = weakTypeOf[T[_]]
val clsName = TypeName(c.freshName())
val r = q"""
final class $clsName extends _root_.test.Gen[$tpe] { }
new $clsName()
"""
println(r)
r
}
}
// compile and call it
Gen[Future] // OK
/*
{
final class fresh$macro$1 extends _root_.utils.Gen[scala.concurrent.Future] {
def <init>() = {
super.<init>();
()
};
<empty>
};
new fresh$macro$1()
}
*/
Gen[P2] // OK
/*
{
final class fresh$macro$2 extends _root_.utils.Gen[P2] {
def <init>() = {
super.<init>();
()
};
<empty>
};
new fresh$macro$2()
}
*/
Gen[({type λ[A] = P[Int, A]})#λ] // KO
/* F is not inferred due to SI-2712 :(
{
final class fresh$macro$3 extends _root_.utils.Gen[F] {
def <init>() = {
super.<init>();
()
};
<empty>
};
new fresh$macro$3()
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment