Last active
May 12, 2016 03:24
-
-
Save mandubian/4f828e659a7e98e0dcfb to your computer and use it in GitHub Desktop.
SI-2712 by the examples
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 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