Reflection with Typeclasses - scala

I'm writing a little registration module for some application and doing this with typeclasses. Main logic is based on Spray routing:
val api = post {
path("register" / Rest) { rest =>
rest match {
case "user" => register[User]
// ... other cases
}
}
}
}
To simplify i have the following data type for User:
case class User(id: String, email: String)
And to extract entity from POST request i'm using typeclass:
trait EntityExtractor[T] {
def extractFromRequest: Directive[T :: String :: HNil]
}
implementation for user:
object User {
implicit val extractor = new EntityExtractor[User] {
def extractFromRequest: Directive[User :: String :: HNil] =
formFields('email, 'pass).hmap {
case email :: pass :: HNil =>
val id = UID.genId
User(id, email) :: pass :: HNil
}
}
}
The problem arises in my register method which uses a typeclass directive:
def register[T] =
extractEntity[T].apply { entity => // fails here
validateEntity(entity) {
completeRegistration(entity)
}
}
}
def extractEntity[T: EntityExtractor]: Directive[Entity[T] :: HNil] = {
implicitly[EntityExtractor[T]].extractFromRequest.hmap {
case entity :: pass :: HNil => Entity(entity, pass) :: HNil
}
}
And it fail with an exception: could not find implicit value for evidence parameter of type EntityExtractor[T].
Is there any way to fix this with reflection (TypeTags or Manifest) without pattern matching?

Hope the following somewhat contrived example will clarify the whole matter a bit.
Consider this code (which corresponds to your current one):
object Main {
def main(args: Array[String]) {
implicit val intIntable = new Intable[Int] {
def toInt(obj: Int) = obj
}
println(squareAndDouble(10: Int))
}
// Corresponds to your register[T] function
def squareAndDouble[T](obj: T) = {
val d = double[T](obj)
d*d
}
// Corresponds to your extractEntity[T] function
def double[T: Intable](obj: T) = {
implicitly[Intable[T]].toInt(obj)*2
}
}
trait Intable[T] {
def toInt(obj: T): Int
}
This code does not compile with the following error:
test.scala:11: error: could not find implicit value for evidence parameter of type Intable[T]
val d = double[T](obj)
Now let's rewrite it using implicit parameters (that's what the compiler do for us when it sees context bound):
object Main {
def main(args: Array[String]) {
implicit val intIntable = new Intable[Int] {
def toInt(obj: Int) = obj
}
println(squareAndDouble(10: Int))
}
def squareAndDouble[T](obj: T) = {
val d = double[T](obj)
d*d
}
def double[T](obj: T)(implicit intable: Intable[T]) = {
intable.toInt(obj)*2
}
}
trait Intable[T] {
def toInt(obj: T): Int
}
This program does not compile as well:
test.scala:11: error: could not find implicit value for parameter intable: Intable[T]
val d = double[T](obj)
And now it should be more obvious why it does not compile. It fails simply because there is no implicit value ('evidence') for T type parameter inside squareAndDouble function which is required by square function. Since double function need an evidence for its type parameter (which can be anything) the only way for this evidence to appear in scope inside squareAndDouble is from an implicit parameter again, but now in squareAndDouble function.
Basically, that means that you have to 'pass through' the evidence for your generic parameter in order to use the typeclass.
Let's fix it:
object Main {
def main(args: Array[String]) {
implicit val intIntable = new Intable[Int] {
def toInt(obj: Int) = obj
}
println(squareAndDouble(10: Int))
}
// Added context bound here
def squareAndDouble[T: Intable](obj: T) = {
val d = double[T](obj)
d*d
}
def double[T: Intable](obj: T) = {
implicitly[Intable[T]].toInt(obj)*2
}
}
trait Intable[T] {
def toInt(obj: T): Int
}
Now it compiles and runs successfully:
% scalac test.scala
% scala Main
400
Another (may be more simple) way to understand the problem is as follows. Our squareAndDouble[T] function accepts unbounded type parameter T, but then it tries to call another function, double[T: Intable], whose type parameter is bounded. This is not allowed: if it was legal, then it would be possible to call squareAndDouble[T] with any type, even with that which does not have Intable typeclass instance, and this would consequently break double function. Hence we have to add Intable boundary to squareAndDouble function too in order for it to compile: squareAndDouble[T: Intable], and then it works perfectly.
This is in fact very similar to upper/lower bounds which work with class inheritance instead of implicit values.

Related

Scala parsing generic argument of a function

I want to build a function that takes as input a generic function with one argument,
than parse the argument based on type and call the input function:
class PatternMatching {
val a = "test"
def test[T: TypeTag](callback: T => Unit): Unit = {
callback match {
case x if typeOf[T] <:< typeOf[String] => callback(a)
case x if typeOf[T] <:< typeOf[Array[Char]] => callback(a.toCharArray)
case _ => throw new IllegalArgumentException("error")
}
}
}
I see that type is correctly inferred but is not possible to invoke the function:
type mismatch;
found : PatternMatching.this.a.type (with underlying type String)
required: T
case x if typeOf[T] <:< typeOf[String] => callback(a)
I understand that it's expecting a type, but I can't find a way out.
You need explicit .asInstanceOf[T] with the method you've written:
callback(a.asInstanceOf[T])
Though, what you're trying to achieve is typically done with typeclass in Scala. I let the reader search about it but the general idea is you would have your method defined like this:
def test[T](callback: T => Unit)(implicit converter: ConverterFromString[T]): Unit = {
callback(converter.fromString(a))
}
And there would exist in scope some values of ConverterFromString for only some types you know how to handle.
The huge benefit of this approach is to be type-safe and if will raise errors at compile time rather than runtime if a type cannot be handled.
Using typeclass as suggested by #Gaƫl J works:
trait Converter[A] {
def conveterFromString(a: String): A
}
object Converter {
implicit val stringConverter: Converter[String] = new Converter[String] {
def conveterFromString(x: String): String = x
}
implicit val arrayConverter: Converter[Array[Char]] = new Converter[Array[Char]] {
def conveterFromString(x: String): Array[Char] = x.toCharArray
}
}
class PatternMatching {
val a = "test"
def test[A](callback: A => Unit)(implicit converter: Converter[A]): Unit =
callback(converter.conveterFromString(a))
}

Accessing implicit parameters explicitly at runtime

I'm trying to access an implicit parameter for a generic type. Scala is able to find the implicit just fine in the straightforward case by calling a method with an explicit generic type, such as with printGenericType[Person] below.
However, if I create a TypeTag[Person] and pass it to printGenericTypeGivenTypeTag, Scala is unable to find the implicit parameter.
case class Person(name: String)
case class Animal(age: Int)
implicit val p = Person("cory")
implicit val a = Animal(2)
def main(args: Array[String]): Unit = {
// Can find the implicit Person, prints "Hello Person(cory)"
printGenericType[Person]
// Can find the implicit Animal, prints "Hello Animal(2)"
printGenericType[Animal]
// See comment below
printNamedType("Person")
printNamedType("Animal")
}
def printGenericType[T](implicit t: T) = {
println(s"Hello $t")
}
def printGenericTypeGivenTypeTag[T](typeTag: TypeTag[T])(implicit t: T) = {
println(s"Hello $t")
}
def printNamedType[T](name: String) = {
val typetag: TypeTag[T] = getTypeTag[T](name)
// Cannot find the implicit of type T, compiler error
printGenericTypeGivenTypeTag(typetag)
}
def getTypeTag[T](name:String): TypeTag[T] = ... //Implementation irrelevant
If I understand correctly, Scala locates implicit parameters at compile time, so it makes sense that it can't find an implicit parameter for the generic type T at compile time.
However, I know that an implicit instance of T does exist. Is it possible to rewrite printGenericTypeGivenTypeTag in such a way as to find the implicit value for T? At runtime, the method has access to the actual type of T, so it seems it should be able to locate an implicit parameter of the same type that is in scope.
For the curious, the reasoning behind this is to avoid this:
name match {
case "Person" => printGenericType[Person]
case "Animal" => printGenericType[Animal]
}
To answer the question
You're not really wanting to pass the T implicitly, but rather the TypeTag, and not the T. Here's what I mean, and you're probably better off with an implicit value class.
implicit class GenericPrinter[T](val obj: T) extends AnyVal {
def printGenericType()(implicit tag: TypeTag[T]) = {
// do stuff with the tag
Console.println("Hello $obj")
}
}
val x: Person = Person(...)
x.printGenericType
Now solving the real problem
If you are trying to print case classes, I'd probably go down the implicit macro route for added convenience. It's really trivial to write up a macro that does this for us, e.g output a debug string based on all the constructor params of an arbitrary case class.
trait DeepPrinter[T <: Product with Serializable] {
/**
* Prints a deeply nested debug string for a given case class.
* This uses implicit macros to materialise the printer type class.
* In English, when we request for an implicit printer: DeepPrinter[T],
* the pre-defined compile time macro will generate this method for us
* based on the fields of the given case class.
*
* #param sep A separator to use to delimit the rows in a case class.
* #return A fully traced debug string so we can see how a case class looks like.
*/
def debugString(sep: String = "\n"): String
}
object DeepPrinter {
implicit def deepPrinter[T <: Product with Serializable] = macro DeepPrinterImpl.deepPrinterImpl[T]
}
And the macro is pretty trivial, looks kind of like this.
import language.experimental.macros
import scala.reflect.macros.blackbox
#macrocompat.bundle
class DeepPrinterImpl(val c: blackbox.Context) {
import c.universe._
object CaseField {
def unapply(symbol: TermSymbol): Option[(Name, Type)] = {
if (symbol.isVal && symbol.isCaseAccessor) {
Some(symbol.name -> symbol.typeSignature)
} else {
None
}
}
}
def fields(tpe: Type): Iterable[(Name, Type)] = {
tpe.decls.collect { case CaseField(nm, tpeSn) => nm -> tpeSn }
}
def materialize[T : c.WeakTypeTag]: c.Expr[DeepPrinter[T]] = {
val tpe = weakTypeOf[T]
val (names, types) = fields(tpe).unzip
// change the package name to the correct one here!
val tree = q"""
new com.bla.bla.DeepPrinter[$tpe] {
def debugString(sep: String = "\n") = Seq(..$names).mkString(sep)
}
"""
c.Expr[DeepPrinter[T]](tree)
}
}

How to solve method delegation with scala implicits

How can i solve this simple problem. Class Conversion has a typed method from wich takes two type parameters A and B and returns a B from an A. I have defined some implicits in the companion object to provide default beahviour.
My Problem is when i try to forward the call to the Conversion class within another typed method which has the same signature it does not work. Here in my example i try to forward the call from function myFun to my Conversion class.
I got following error
not enough arguments for method from: (implicit f: A => B)
I am wondering why this makes any problems. Can someone explain me why and how to overcome this problem ?
Here is the code
object MyConversions {
implicit val IntToStr = (f:Int) => f.toString()
implicit val DoubleToStr = (f:Double) => f.toString()
implicit val BooleanToStr = (f:Boolean) => f.toString()
}
class Conversions{
def from[A,B](a:A)(implicit f:(A) => B) = {
f(a)
}
}
import MyConversions._;
def myFun[A,B](a:A){
// Error
new Conversions().from[A, B](a)
}
// Working
println( new Conversions().from[Int, String](3) )
The problem is that the Scala compiler cannot find an implicit value for the parameter f: (A) => B in the scope of myFun. What you have to do is to tell the compiler that myFun can only be called, when there is such a value available.
The following code should do the trick
object App {
trait Convertible[A, B] {
def convert(a: A): B
}
object Convertible {
implicit val int2String = new Convertible[Int, String] {
override def convert(a: Int): String = a.toString
}
implicit val float2String = new Convertible[Float, String] {
override def convert(a: Float): String = a.toString
}
}
def myFun[A ,B](a:A)(implicit converter: Convertible[A, B]): B = {
converter.convert(a)
}
def main(args: Array[String]): Unit = {
println(myFun(3))
}
}

How to overload the product method of a typeclass

I am trying to implement a ReadJsonCodec of sorts using the automatic type class derivation mechanism in Shapeless.
Here is my ReadCodecCompanionObject:
object ReadCodec extends LabelledProductTypeClassCompanion[ReadCodec] {
implicit object StringCodec extends SimpleCodec[String] {
def read(j: Json): String = j.stringOr(throw ...)
}
implicit object IntCodec ...
implicit object BooleanCodec ...
implicit object LongCodec ...
implicit object ShortCodec ...
implicit object DoubleCodec ...
implicit object BigDecimalCodec ...
implicit def readCodecInstance: LabelledProductTypeClass[ReadCodec] = new LabelledProductTypeClass[ReadCodec] {
def emptyProduct = new ReadCodec[HNil] {
// This will silently accept extra fields within a JsonObject
// To change this behavior make sure json is a JsonObject and that it is empty
def read(json: Json) = HNil
}
def product[F, T <: HList](name: String, FHead: ReadCodec[F], FTail: ReadCodec[T]) = new ReadCodec[F :: T] {
def read(json: Json): F :: T = {
val map = castOrThrow(json)
val fieldValue = map.getOrElse(name, throw new MappingException(s"Expected field $name on JsonObject $map"))
// Try reading the value of the field
// If we get a mapping exception, intercept it and add the name of this field to the path
// If we get another exception, don't touch!
// Pitfall: if handle did not accept a PartialFunction, we could transform an unknow exception into a match exception
val head: F = Try(FHead.read(fieldValue)).handle{ case MappingException(msg, path) => throw MappingException(msg, s"$name/$path")}.get
val tail = FTail.read(json)
head :: tail
}
}
def product[A, T <: HList](name: String, FHead: ReadCodec[Option[A]], FTail: ReadCodec[T]) = new ReadCodec[Option[A] :: T] {
def read(json: Json): Option[A] :: T = {
val map = castOrThrow(json)
val head: Option[A] = map.get(name).map { fieldValue =>
Try(FHead.read(fieldValue)).handle{ case MappingException(msg, path) => throw MappingException(msg, s"$name/$path")}.get.get
}
val tail = FTail.read(json)
head :: tail
}
}
def project[F, G](instance: => ReadCodec[G], to : F => G, from : G => F) = new ReadCodec[F] {
def read(json: Json): F = from(instance.read(json))
}
}
}
That's somewhat of a complicated piece of code to just grasp quickly but is really fairly simple once you understand it. The important part is the two def product methods. The problem I am having is that I want this codec to accept a Json AST that is missing a field if that field would be mapped to a value of type Option[A]. This means that I need the product function to know if the head of the HList is of type Option[A] or not.
Concretely:
case class Foo(a: String, b: Option[Boolean])
val test = read[Foo](json"""{"a" : "Beaver"}""") // should work
But currently this would fail because it makes no distinction for Option and expects a field b. I tried two ways of fixing this and neither of them worked.
The first one and the cleanest one is to overload the product method with a version where the F type parameter is replaced with Option[A]. This approach is fairly clean, although I am not sure whether or not it would play well with the shapeless derivation macro. However, it is not possible because Scala does not support the ability to overload functions when the type signature after erasure is the same. This is the version that is above. Unfortunately, this does not currently compile with the Scala compiler.
The second approach was to use a TypeTag to find out at runtime if F is of type Option[_] and behave appropriately. This version would almost certainly be less elegant and involve a cast but I could live with it. However, it seems impossible because the addition of a TypeTag changes the signature of the product method (adding an implicit parameter) and then the compiler complains that I am not defining the abstract method product.
Does anyone have any suggestions on the best way to proceed.
You need to get a typeclass with information about F passed through. But you're already passing a typeclass around, in the form of ReadCodec. So the solution is to replace that with one that contains all the information you need:
trait ReadCodecAndTypeTag[A] {
val rc: ReadCodec[A]
val tt: TypeTag[A]
}
But in that case you might as well delegate the decoding-from-optional-value-in-a-map to this typeclass as well:
trait OReadCodec[A] {
val rc: ReadCodec[A]
def missingField(name: String, map: Any): A =
throw new MappingException(s"Expected field $name on JsonObject $map")
}
implicit object StringCodec extends OReadCodec[String] {
val rc = new ReadCodec[String] {...}
}
implicit object IntCodec ...
...
implicit def OptionCodec[A](implicit orc: OReadCodec[A]) =
new OReadCodec[Option[A]] {
val rc = ...
override def missingField(name: String, map: Any) = None
}
...
def product[F, T <: HList](name: String, FHead: OReadCodec[F], FTail: OReadCodec[T]) =
new OReadCodec[F :: T] {
val rc = new ReadCodec[F :: T] {
def read(json: Json): F :: T = {
val map = castOrThrow(json)
val fieldValue = map.getOrElse(name, FHead.missingField(name, map))
val head: F = ...
...
}
}
}
implicit def ReadCodecFromOReadCodec[A](implicit orc: OReadCodec[A]) = orc.rc

How to specify the return type of a function to be a (arbitrary) monad?

In short, I want to declare a trait like this:
trait Test {
def test(amount: Int): A[Int] // where A must be a Monad
}
so that I can use it without knowing what monad that A is, like:
class Usecase {
def someFun(t: Test) = for { i <- t.test(3) } yield i+1
}
more details...
essentially, I want to do something like this:
class MonadResultA extends SomeUnknownType {
// the base function
def test(s: String): Option[Int] = Some(3)
}
class MonadResultB(a: MonadResultA) extends SomeUnknownType {
// added a layer of Writer on top of base function
def test(s: String): WriterT[Option, String, Int] = WriterT.put(a.test(s))("the log")
}
class Process {
def work(x: SomeUnknownType) {
for {
i <- x.test("key")
} yield i+1
}
}
I wanted to be able to pass any instances of MonadResultA or MonadResultB without making any changes to the function work.
The missing piece is that SomeUnknowType, which I guess should have a test like below to make the work function compiles.
trait SomeUnknowType {
def test(s: String): T[Int] // where T must be some Monad
}
As I've said, I'm still learning this monad thing... if you find my code is not the right way to do it, you're more than welcomed to point it out~
thanks a lot~~
Assuming you have a type class called Monad you can just write
def test[A:Monad](amount: Int): A[Int]
The compiler will require that there is an implicit of type Monad[A] in scope when test is called.
EDIT:
I'm still not sure what you're looking for, but you could package up a monad value with its corresponding type class in a trait like this:
//trait that holds value and monad
trait ValueWithMonad[E] {
type A[+E]
type M <: Monad[A]
val v:A[E]
val m:M
}
object M {
//example implementation of test method
def test(amount:Int):ValueWithMonad[Int] = new ValueWithMonad[Int] {
type A[+E] = Option[E]
type M = Monad[Option]
override val v = Option(amount)
override val m = OptionMonad
}
//test can now be used like this
def t {
val vwm = test(1)
vwm.m.bind(vwm.v, (x:Int) => {
println(x)
vwm.m.ret(x)
})
}
}
trait Monad[A[_]] {
def bind[E,E2](m:A[E], f:E=>A[E2]):A[E2]
def ret[E](e:E):A[E]
}
object OptionMonad extends Monad[Option] {
override def bind[E,E2](m:Option[E], f:E=>Option[E2]) = m.flatMap(f)
override def ret[E](e:E) = Some(e)
}