Building a compiler for Free monad (Cats library) - scala

I'm trying to get my head around monads and Cats. Following some examples (e.g.cats) I wrote the code like below. But can't figure out how to make compiler to do what I need and to compile, actually.
import cats.Id
import cats.free.Free
import cats.~>
object Filtering extends App {
sealed trait Filter[A]
case class WhitespaceFilter(text: String) extends Filter[Seq[String]]
case class LowerCaseFilter(strings: Seq[String]) extends Filter[Seq[String]]
def whitespaceFilter(text: String): Free[Filter, Seq[String]] = Free.liftF(WhitespaceFilter(text))
def lowerCaseFilter(strings: Seq[String]): Free[Filter, Seq[String]] = Free.liftF(LowerCaseFilter(strings))
val process: (String => Free[Filter, Seq[String]]) = {
text: String =>
for {
p1 <- whitespaceFilter(text)
p2 <- lowerCaseFilter(p1)
} yield p2
}
def compiler: Filter ~> Id =
new (Filter ~> Id) {
def apply[A](fa: Filter[A]): Id[A] =
fa match {
// The code doesn't compile if uncommented...
case WhitespaceFilter(text) => ??? // text.trim.split("""[\s]+""")
case LowerCaseFilter(terms) => ??? // terms.map(_.toLowerCase)
}
}
val result: Seq[String] = process("Some Text").foldMap(compiler)
println(result) // should be Seq("some", "text")
}
Thanks!

I had a similar problem when playing around with the Cats example code you cited. I'm running IntelliJ IDEA and the IDE marks the commented lines with compiler errors but I can in fact run the code and get the output:
ArrayBuffer(some, text)
I think that IntelliJ's compiler is getting confused by the definition of Id:
type Id[A] = A
I'm not sure if IntelliJ uses it's own compiler or if it uses the Scala compiler. If the latter is true, there may be a way to get IntelliJ to use a more recent compiler that handles this type definition.
Good luck! :)

Related

What's the best way to store different types in a collection

I have a generic class:
class GenericType[T] {
def func(t: T) = ???
}
I need to implement a function that takes a List[String] and outputs the corresponding GenericType[T]. For example, if a client passes in List("SomeType1", "SomeType2"), the function should return List(GenericType[SomeType1], GenericType[SomeType2]). Basically, there's a string that maps to a type.
I don't find a good way to represent the return type for such function. Seq[GenericType[_]] as the return type can be an option but it requires the client to cast it into corresponding subclasses to invoke func as the type info is lost.
Alternatively, a case class can be used but this is not flexible as I need to modify the case class every time a new subclass is added.
case class (s1: Option[GenericType[SomeType1]] = None, s2: Option[SomeType2] = None, ...)
I'm curious what's a good way to represent the return type?
The easiest is
def stringToGenericType(s: String): GenericType[_] = s match {
case "SomeType1" => new GenericType[SomeType1]
case "SomeType2" => new GenericType[SomeType2]
}
GenericType[_] (or GenericType[Any] if you make GenericType covariant: class GenericType[+T]) would be an honest return type. You can't know at compile time which specific GenericType[...] you return based on a runtime string. Anyway you can't avoid casting somewhere because you can't guarantee the type statically. Anyway this kind of programming can't be type-safe.
Since we're doing a choice based on a runtime string, compile-time techniques (macros, implicits, Shapeless) are off the table. (*)
Actually, currently you don't need even runtime reflection. Your class GenericType[T] and method func in it seem not to do anything at runtime differently depending on type T. GenericType[SomeType1] and GenericType[SomeType2] are just GenericType[_] at runtime. So even the following implementation is possible
def stringToGenericType(s: String): GenericType[_] = new GenericType[Any]
Another situation would be if you created instances of different classes
class GenericType1[T]
class GenericType2[T]
import scala.reflect.runtime
import scala.reflect.runtime.universe._
val runtimeMirror = runtime.currentMirror
def stringToGenericTypeX(s: String): Any = {
val classSymbol = runtimeMirror.staticClass(s)
val constructorSymbol = classSymbol.typeSignature.decl(termNames.CONSTRUCTOR).asMethod
runtimeMirror.reflectClass(classSymbol).reflectConstructor(constructorSymbol).apply()
}
or you called different methods
class GenericType[T] {
def func1(t: T) = ???
def func2(t: T) = ???
}
def callFuncX(methodName: String, t: Any) = {
val classSymbol = runtimeMirror.classSymbol(classOf[GenericType[_]])
val methodSymbol = classSymbol.typeSignature.decl(TermName(methodName)).asMethod
runtimeMirror.reflect(new GenericType[Any]).reflectMethod(methodSymbol).apply(t)
}
or something behaved at runtime differently depending on type T
class GenericType[T: ClassTag] {
def func(t: T) = println(classTag[T].runtimeClass)
}
import scala.tools.reflect.ToolBox
val toolbox = runtimeMirror.mkToolBox()
def stringToGenericType(s: String): GenericType[_] = {
toolbox.eval(q"new GenericType[${TypeName(s)}]").asInstanceOf[GenericType[_]]
}
(*) Well, actually the first pattern matching (as I wrote it) can be automated with a macro
// in a different subproject
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def stringToGenericType(s: String): GenericType[_] = macro stringToGenericTypeImpl
def stringToGenericTypeImpl(c: blackbox.Context)(s: c.Tree): c.Tree = {
import c.universe._
val cases = List("SomeType1", "SomeType2").map(str =>
cq"$str => new GenericType[${TypeName(str)}]"
)
q"$s match { case ..$cases }"
}
val s = "SomeTime1"
stringToGenericType(s)
// scalacOptions += "-Ymacro-debug-lite"
//s match {
// case "SomeType1" => new GenericType[SomeType1]()
// case "SomeType2" => new GenericType[SomeType2]()
//}

Class type required but E found (scala macro)

I'm trying to remove some of the boilerplate in an API I am writing.
Roughly speaking, my API currently looks like this:
def toEither[E <: WrapperBase](priority: Int)(implicit factory: (String, Int) => E): Either[E, T] = {
val either: Either[String, T] = generateEither()
either.left.map(s => factory(s, priority))
}
Which means that the user has to generate an implicit factory for every E used. I am looking to replace this with a macro that gives a nice compile error if the user provided type doesn't have the correct ctor parameters.
I have the following:
object GenericFactory {
def create[T](ctorParams: Any*): T = macro createMacro[T]
def createMacro[T](c: blackbox.Context)(ctorParams: c.Expr[Any]*)(implicit wtt: WeakTypeType[T]): c.Expr[T] = {
import c.universe._
c.Expr[T](q"new $wtt(..$ctorParams)")
}
}
If I provide a real type to this GenericFactory.create[String]("hey") I have no issues, but if I provide a generic type: GenericFactory.create[E]("hey") then I get the following compile error: class type required by E found.
Where have I gone wrong? Or if what I want is NOT possible, is there anything else I can do to reduce the effort for the user?
Sorry but I don't think you can make it work. The problem is that Scala (as Java) uses types erasure. It means that there is only one type for all generics kinds (possibly except for value-type specializations which is not important now). It means that the macro is expanded only once for all E rather then one time for each E specialization provided by the user. And there is no way to express a restriction that some generic type E must have a constructor with a given signature (and if there were - you wouldn't need you macro in the first place). So obviously it can not work because the compiler can't generate a constructor call for a generic type E. So what the compiler says is that for generating a constructor call it needs a real class rather than generic E.
To put it otherwise, macro is not a magic tool. Using macro is just a way to re-write a piece of code early in the compiler processing but then it will be processed by the compiler in a usual way. And what your macro does is rewrites
GenericFactory.create[E]("hey")
with something like
new E("hey")
If you just write that in your code, you'll get the same error (and probably will not be surprised).
I don't think you can avoid using your implicit factory. You probably could modify your macro to generate those implicit factories for valid types but I don't think you can improve the code further.
Update: implicit factory and macro
If you have just one place where you need one type of constructors I think the best you can do (or rather the best I can do ☺) is following:
Sidenote the whole idea comes from "Implicit macros" article
You define StringIntCtor[T] typeclass trait and a macro that would generate it:
import scala.language.experimental.macros
import scala.reflect.macros._
trait StringIntCtor[T] {
def create(s: String, i: Int): T
}
object StringIntCtor {
implicit def implicitCtor[T]: StringIntCtor[T] = macro createMacro[T]
def createMacro[T](c: blackbox.Context)(implicit wtt: c.WeakTypeTag[T]): c.Expr[StringIntCtor[T]] = {
import c.universe._
val targetTypes = List(typeOf[String], typeOf[Int])
def testCtor(ctor: MethodSymbol): Boolean = {
if (ctor.paramLists.size != 1)
false
else {
val types = ctor.paramLists(0).map(sym => sym.typeSignature)
(targetTypes.size == types.size) && targetTypes.zip(types).forall(tp => tp._1 =:= tp._2)
}
}
val ctors = wtt.tpe.decl(c.universe.TermName("<init>"))
if (!ctors.asTerm.alternatives.exists(sym => testCtor(sym.asMethod))) {
c.abort(c.enclosingPosition, s"Type ${wtt.tpe} has no constructor with signature <init>${targetTypes.mkString("(", ", ", ")")}")
}
// Note that using fully qualified names for all types except imported by default are important here
val res = c.Expr[StringIntCtor[T]](
q"""
(new so.macros.StringIntCtor[$wtt] {
override def create(s:String, i: Int): $wtt = new $wtt(s, i)
})
""")
//println(res) // log the macro
res
}
}
You use that trait as
class WrapperBase(val s: String, val i: Int)
case class WrapperChildGood(override val s: String, override val i: Int, val float: Float) extends WrapperBase(s, i) {
def this(s: String, i: Int) = this(s, i, 0f)
}
case class WrapperChildBad(override val s: String, override val i: Int, val float: Float) extends WrapperBase(s, i) {
}
object EitherHelper {
type T = String
import scala.util._
val rnd = new Random(1)
def generateEither(): Either[String, T] = {
if (rnd.nextBoolean()) {
Left("left")
}
else {
Right("right")
}
}
def toEither[E <: WrapperBase](priority: Int)(implicit factory: StringIntCtor[E]): Either[E, T] = {
val either: Either[String, T] = generateEither()
either.left.map(s => factory.create(s, priority))
}
}
So now you can do:
val x1 = EitherHelper.toEither[WrapperChildGood](1)
println(s"x1 = $x1")
val x2 = EitherHelper.toEither[WrapperChildGood](2)
println(s"x2 = $x2")
//val bad = EitherHelper.toEither[WrapperChildBad](3) // compilation error generated by c.abort
and it will print
x1 = Left(WrapperChildGood(left,1,0.0))
x2 = Right(right)
If you have many different places where you want to ensure different constructors exists, you'll need to make the macro much more complicated to generate constructor calls with arbitrary signatures passed from the outside.

Import implicits from object that passed as method parameter vs class constructor parameter

I have the following code:
case class Custom(value: Int)
case class Custom2(value: Float)
case class MappedEncoding[I, O](f: I => O)
trait Decoders {
type BaseDecoder[T] = () => T
type Decoder[T] <: BaseDecoder[T]
}
trait ConcreteDecoders extends Decoders {
type Decoder[T] = ConcreteDecoder[T]
case class ConcreteDecoder[T](decoder: () => T) extends BaseDecoder[T] {
def apply(): T = decoder()
}
implicit def optionDecoder[T](implicit d: Decoder[T]): Decoder[Option[T]] =
ConcreteDecoder[Option[T]](() => Some(d()))
implicit def mappedDecoder[I, O](implicit mapped: MappedEncoding[I, O], decoder: Decoder[I]): Decoder[O] =
ConcreteDecoder[O](() => mapped.f(decoder()))
implicit def intDecoder: Decoder[Int] = ConcreteDecoder[Int](() => 1)
implicit def floatDecoder: Decoder[Float] = ConcreteDecoder(() => 1)
}
class ConcreteContext extends ConcreteDecoders {
}
case class TestObject() {
implicit val customDecoder = MappedEncoding[Int, Custom](Custom)
implicit val custom2Encoder = MappedEncoding[Custom2, Float](_.value) // 1
implicit val custom2Decoder = MappedEncoding[Float, Custom2](Custom2)
def a(c: ConcreteContext): Unit = {
import c._
implicitly[Decoder[Option[Custom]]] // 2
// implicitly[Decoder[Float]] // 3
implicitly[Decoder[Option[Float]]]
()
}
}
object Main extends App {
implicit val c = new ConcreteContext()
TestObject().a(c)
// TestObject(a).()
}
And it does not compile in Scala 2.11.8 and 2.12.0 with error:
diverging implicit expansion for type c.Decoder[Option[Float]]
[error] starting with method intDecoder in trait ConcreteDecoders
[error] implicitly[Decoder[Option[Float]]]
Using -Xlog-implicits option gives long output but the most interesting part is:
floatDecoder is not a valid implicit value for c.Decoder[Float] because:
[info] diverging implicit expansion for type c.Decoder[T]
[info] starting with method intDecoder in trait ConcreteDecoders
[info] implicitly[Decoder[Option[Float]]]
Moving c: CustomContext from method parameter to case class constructor parameter makes it compile. I thought that may be it changes implicits search scope.
Also one of the following actions make it compile:
commenting line marked with comment 1 (== line 1)
commenting line 2
uncommenting line 3
It looks like resolving implicitly[Decoder[Option[Custom]]] leaves Scala compiler in state that affects resolving implicitly[Decoder[Option[Float]]].
Why is this happening and how can I make it compile without moving c: ConcreteContext from method parameter?
P.S. This is simplified code that reproduces the issue. The real code is much more complex and I need to support the case when ConcreteContext is passed as a method parameter.
This is not a full answer.
I haven't any satisfactory explanation why mention of another implicit could drive resolution out of the loop, created by mappedEncoder with custom2Encoder + custom2Decoder pair. I can only guess that existence of implicitly[Decoder[Float]] is upping floatDecoder priority over noted custom2... loop.
But there is nice solution, which may be not the best but viable option, called
shapeless.Lazy. It sometimes can be used instead of LowPriority decomposition to handle more dreadful situation like this.
You can just rewrite your mappedDecoder as
import shapeless.Lazy
implicit def mappedDecoder[I, O]
(implicit mapped: MappedEncoding[I, O],
decoder: Lazy[Decoder[I]]): Decoder[O] =
ConcreteDecoder[O](() => mapped.f(decoder.value()))
to make original code work

Compile errors when defining a macro to convert a case class instance into a map and back

I'm trying to understand the following blog post, which discusses how to use macros to create a generic macro-based approach to convert case class objects to and from a map: http://blog.echo.sh/post/65955606729/exploring-scala-macros-map-to-case-class-conversion
Even though I read the entire post and another article on scala macros, I still do not fully understand how they work. Unfortunately, I'm receiving a couple of compile errors from the example code given in the blog post and am not sure why the errors are occurring nor how to resolve them. I'm reproducing the code below, preceded by the compile errors, for completeness (I annotated the code snippet with comments regarding the compile errors). Does anyone know why these compiler issues are occurring and how to resolve them?
-type mismatch; found : field.NameType required:
c.universe.TermName
-Can't unquote List[Nothing] with .., bottom type values often indicate programmer mistake
Here's the code:
import scala.reflect.macros.Context
import scala.language.experimental.macros
trait Mappable[T] {
def toMap(t: T): Map[String, Any]
def fromMap(map: Map[String, Any]): T
}
object Mappable {
implicit def materializeMappable[T]: Mappable[T] = macro materializeMappableImpl[T]
def materializeMappableImpl[T: c.WeakTypeTag](c: Context): c.Expr[Mappable[T]] = {
import c.universe._
val tpe = weakTypeOf[T]
val companion = tpe.typeSymbol.companionSymbol
val fields = tpe.declarations.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor ⇒ m
}.get.paramss.head
val (toMapParams, fromMapParams) = fields.map { field ⇒
val name = field.name
val decoded = name.decoded
val returnType = tpe.declaration(name).typeSignature
(q"$decoded → t.$name", q"map($decoded).asInstanceOf[$returnType]") // error 1
}.unzip
c.Expr[Mappable[T]] {
q"""
new Mappable[$tpe] {
def toMap(t: $tpe): Map[String, Any] = Map(..$toMapParams)
def fromMap(map: Map[String, Any]): $tpe = $companion(..$fromMapParams) // error 2
}
"""
}
}
}
change t.$name to t.${name.toTermName}

Using attachments with macros in Scala 2.10

Update: I suspect that what I want might not be possible, and I've written up a blog post with my reasoning (and some alternatives) here. I'd be very happy to be told that I'm wrong.
Suppose I want to create a instance of a trait using a factory method with a macro implementation. This method will take as an argument a path to a resource that the macro will read and parse (at compile time) into a map from strings to strings.
That part is all fairly straightforward. Now suppose I want to associate the resulting map with the instance I'm creating so that I can use it in subsequent macro calls involving that instance.
I crucially do not want the map to be a member of the instance, or to exist in any form at runtime. I also don't want to parse the same resource more than once. Here's a sketch of the kind of thing I'm aiming for:
import scala.language.experimental.macros
import scala.reflect.macros.Context
trait Foo {
def lookup(key: String): String = macro Foo.lookup_impl
}
object Foo {
def parseResource(path: String): Map[String, String] = ???
def apply(path: String): Foo = macro apply_impl
def apply_impl(c: Context)(path: c.Expr[String]): c.Expr[Foo] = {
import c.universe._
val m = path.tree match {
case Literal(Constant(s: String)) => parseResource(s)
}
val tree = reify(new Foo {}).tree
// Somehow associate the map with this tree here.
c.Expr(tree)
}
def lookup_impl(c: Context)(key: c.Expr[String]): c.Expr[String] =
/* Somehow read off the map and look up this key. */ ???
}
This seems to be the sort of thing that attachments are designed to help with (thanks to Eugene Burmako for the pointer), and I've got an attachment-based implementation that allows me to write the following:
Foo("whatever.txt").lookup("x")
Where apply_impl attaches the map to the tree and lookup_impl reads that attachment off the same tree, which it sees as its prefix. Unfortunately this is more or less useless, though, since it doesn't work in the foo.lookup("x") case, where the prefix tree is just the variable foo.
(Note that in my real use case Foo extends Dynamic, and I'm trying to give a macro implementation for selectDynamic instead of lookup, but that shouldn't be relevant here—I'm interested in the general case.)
Is there some way that I can use attachments to get what I want? Is there some other approach that would be more appropriate?
UPDATE I should read the question again after fiddling... :( I just reproduced what you have.
You were quite there I think. This works for me:
object Foo {
// Attachment.get somehow needs a wrapper class.
// Probably because of generics
implicit class LookupMap(m: Map[String, String]) {
def get(s: String) = m.get(s)
}
def parseResource(path: String): LookupMap = Map("test" -> "a")
def apply_impl(c: Context)(path: c.Expr[String]): c.Expr[Foo] = {
import c.universe._
val m = path.tree match {
case Literal(Constant(s: String)) => parseResource(s)
}
val tree = reify(new Foo {}).tree.updateAttachment(m)
c.Expr(tree)
}
def lookup_impl(c: Context { type PrefixType = Foo })
(key: c.Expr[String]): c.Expr[String] = {
import c.universe._
val m = c.prefix.tree.attachments.get[LookupMap].get
val s = key.tree match {
case Literal(Constant(s: String)) => m.get(s).get
}
c.Expr(Literal(Constant(s)))
}
}