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))
}
}
Related
Given a simple parametrized type like class LK[A], I can write
// or simpler def tagLK[A: TypeTag] = typeTag[LK[A]]
def tagLK[A](implicit tA: TypeTag[A]) = typeTag[LK[A]]
tagLK[Int] == typeTag[LK[Int]] // true
Now I'd like to write an analogue for class HK[F[_], A]:
def tagHK[F[_], A](implicit ???) = typeTag[HK[F, A]]
// or some other implementation?
tagHK[Option, Int] == typeTag[HK[Option, Int]]
Is this possible? I've tried
def tagHK[F[_], A](implicit tF: TypeTag[F[_]], tA: TypeTag[A]) = typeTag[HK[F, A]]
def tagHK[F[_], A](implicit tF: TypeTag[F], tA: TypeTag[A]) = typeTag[HK[F, A]]
but neither works for the obvious reasons (in the first case F[_] is the existential type instead of the higher-kinded one, in the second TypeTag[F] doesn't compile).
I suspect the answer is "it's impossible", but would be very happy if it isn't.
EDIT: we currently use WeakTypeTags as follows (slightly simplified):
trait Element[A] {
val tag: WeakTypeTag[A]
// other irrelevant methods
}
// e.g.
def seqElement[A: Element]: Element[Seq[A]] = new Element[Seq[A]] {
val tag = {
implicit val tA = implicitly[Element[A]].tag
weakTypeTag[Seq[A]]
}
}
trait Container[F[_]] {
def lift[A: Element]: Element[F[A]]
// note that the bound is always satisfied, but we pass the
// tag explicitly when this is used
def tag[A: WeakTypeTag]: WeakTypeTag[F[A]]
}
val seqContainer: Container[Seq] = new Container[Seq] {
def lift[A: Element] = seqElement[A]
}
All of this works fine if we replace WeakTypeTag with TypeTag. Unfortunately, this doesn't:
class Free[F[_]: Container, A: Element]
def freeElement[F[_]: Container, A: Element] {
val tag = {
implicit val tA = implicitly[Element[A]].tag
// we need to get something like TypeTag[F] here
// which could be obtained from the implicit Container[F]
typeTag[Free[F, A]]
}
}
Does this serve your purposes?
def tagHK[F[_], A](implicit tt: TypeTag[HK[F, A]]) = tt
As opposed to using the implicit parameter to get the TypeTag for F and A separately and then composing them, you can directly request the tag you want from the compiler. This passes your test case as desired:
tagHK[Option, Int] == typeTag[HK[Option, Int]] //true
Alternatively, if you have an instance of TypeTag[A] you could try:
object HK {
def apply[F[_]] = new HKTypeProvider[F]
class HKTypeProvider[F[_]] {
def get[A](tt: TypeTag[A])(implicit hktt: TypeTag[HK[F, A]]) = hktt
}
}
Allowing you to do:
val myTT = typeTag[Int]
HK[Option].get(myTT) == typeTag[HK[Option, Int]] //true
I have createOld method that I need to override and I cannot change it. I would like to use TypeTag to pattern match provided type in createNew. The goal is to find out how to call createNew from createOld. My current understanding is that compiler doesn't have enough type information about A in createOld method if it doesn't already come with TypeTag[A].
object TypeTagFromClass {
class C1
class C2
// How to get TypeTag[A] needed by createNew?
def createOld[A](c: Class[A]): A = createNew ???
def createNew[A : TypeTag]: A = {
val result = typeOf[A] match {
case a if a =:= typeOf[C1] => new C1()
case a if a =:= typeOf[C2] => new C2()
}
result.asInstanceOf[A]
}
}
It is possible to create a TypeTag from a Class using Scala reflection, though I'm not sure if this implementation of TypeCreator is absolutely correct:
import scala.reflect.runtime.universe._
def createOld[A](c: Class[A]): A = createNew {
val mirror = runtimeMirror(c.getClassLoader) // obtain runtime mirror
val sym = mirror.staticClass(c.getName) // obtain class symbol for `c`
val tpe = sym.selfType // obtain type object for `c`
// create a type tag which contains above type object
TypeTag(mirror, new TypeCreator {
def apply[U <: Universe with Singleton](m: api.Mirror[U]) =
if (m eq mirror) tpe.asInstanceOf[U # Type]
else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.")
})
}
However, you don't really need full TypeTag if you don't need to inspect generic parameters and full Scala type information. You can use ClassTags for that:
def createNew[A: ClassTag]: A = {
val result = classTag[A].runtimeClass match {
case a if a.isAssignableFrom(classOf[C1]) => new C1()
case a if a.isAssignableFrom(classOf[C2]) => new C2()
}
result.asInstanceOf[A]
}
Or with some implicit sugar:
implicit class ClassTagOps[T](val classTag: ClassTag[T]) extends AnyVal {
def <<:(other: ClassTag[_]) = classTag.runtimeClass.isAssignableFrom(other.runtimeClass)
}
def createNew[A: ClassTag]: A = {
val result = classTag[A] match {
case a if a <<: classTag[C1] => new C1()
case a if a <<: classTag[C2] => new C2()
}
result.asInstanceOf[A]
}
You can simplify that even further by using plain old Java newInstance() method:
def createNew[A: ClassTag]: A = classTag[A].runtimeClass.newInstance().asInstanceOf[A]
This, of course, would only work if you don't need different constructor parameters for different classes.
Calling this createNew from createOld is much simpler than the one with TypeTags:
def createOld[A](c: Class[A]): A = createNew(ClassTag[A](c))
So it is not very safe and correct (cause you don't use the power of scala type system), but you can make (using your logic) to do the following:
def createNew[A](implicit t: TypeTag[A]): A = {
val result: Any = t.tpe.toString match {
case "C1" => new C1
case "C2" => new C2
}
result.asInstanceOf[A]
}
createNew[C1] //> its all ok
createNew[C2] //> its all ok
createNew[C3] //> crashes here; lets pretend we got C3 class
To use it with createOld, just pass implicit argument:
def createOld[A](c: Class[A])(implicit t: TypeTag[A]): A = createNew[A]
createOld[C1] //> its all ok
createOld[C2] //> its all ok
createOld[C3] //> crashes here; lets pretend we got C3 class
I think I should not tell you twice that it is not very good.
We can improve this code by using shapeless:
Lets create a poly function, which has a TypeTag as an argument:
import shapeless._; import scala.reflect.runtime.universe._;
def getTypeTag[T](implicit t: TypeTag[T]) = t //> to get TypeTag of a class
// here is low prority implicit
trait createPolyNewErr extends Poly1 {
implicit def newErr[T] = at[T](_ => "Error can not create object of this class")
}
object createPolyBew extends createPolyNewError {
implicit def newC1 = at[TypeTag[C1]](_ => new C1)
implicit def newC2 = at[TypeTag[C2]](_ => new C2)
}
createPolyNew(getTypeTag[C1]) //> success
createPolyNew(getTypeTag[C2]) //> success
createPolyNew(getTypeTag[C3]) //> String: Error can not create object of this class no crash!
We also can write a function, in order not to use function getTypeTag[T] every time:
def createPoly[T]
(implicit t: TypeTag[T],
cse: poly.Case[createPolyNew.type, TypeTag[T] :: HNil]) = cse(t)
createPoly[C1] //> its all ok
createPoly[C2] //> its all ok
createPoly[C3] //> String: Error can not create object of this class no crash!
I have createOld method that I need to override and I cannot change it. I would like to use TypeTag to pattern match provided type in createNew. The goal is to find out how to call createNew from createOld. My current understanding is that compiler doesn't have enough type information about A in createOld method if it doesn't already come with TypeTag[A].
object TypeTagFromClass {
class C1
class C2
// How to get TypeTag[A] needed by createNew?
def createOld[A](c: Class[A]): A = createNew ???
def createNew[A : TypeTag]: A = {
val result = typeOf[A] match {
case a if a =:= typeOf[C1] => new C1()
case a if a =:= typeOf[C2] => new C2()
}
result.asInstanceOf[A]
}
}
It is possible to create a TypeTag from a Class using Scala reflection, though I'm not sure if this implementation of TypeCreator is absolutely correct:
import scala.reflect.runtime.universe._
def createOld[A](c: Class[A]): A = createNew {
val mirror = runtimeMirror(c.getClassLoader) // obtain runtime mirror
val sym = mirror.staticClass(c.getName) // obtain class symbol for `c`
val tpe = sym.selfType // obtain type object for `c`
// create a type tag which contains above type object
TypeTag(mirror, new TypeCreator {
def apply[U <: Universe with Singleton](m: api.Mirror[U]) =
if (m eq mirror) tpe.asInstanceOf[U # Type]
else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.")
})
}
However, you don't really need full TypeTag if you don't need to inspect generic parameters and full Scala type information. You can use ClassTags for that:
def createNew[A: ClassTag]: A = {
val result = classTag[A].runtimeClass match {
case a if a.isAssignableFrom(classOf[C1]) => new C1()
case a if a.isAssignableFrom(classOf[C2]) => new C2()
}
result.asInstanceOf[A]
}
Or with some implicit sugar:
implicit class ClassTagOps[T](val classTag: ClassTag[T]) extends AnyVal {
def <<:(other: ClassTag[_]) = classTag.runtimeClass.isAssignableFrom(other.runtimeClass)
}
def createNew[A: ClassTag]: A = {
val result = classTag[A] match {
case a if a <<: classTag[C1] => new C1()
case a if a <<: classTag[C2] => new C2()
}
result.asInstanceOf[A]
}
You can simplify that even further by using plain old Java newInstance() method:
def createNew[A: ClassTag]: A = classTag[A].runtimeClass.newInstance().asInstanceOf[A]
This, of course, would only work if you don't need different constructor parameters for different classes.
Calling this createNew from createOld is much simpler than the one with TypeTags:
def createOld[A](c: Class[A]): A = createNew(ClassTag[A](c))
So it is not very safe and correct (cause you don't use the power of scala type system), but you can make (using your logic) to do the following:
def createNew[A](implicit t: TypeTag[A]): A = {
val result: Any = t.tpe.toString match {
case "C1" => new C1
case "C2" => new C2
}
result.asInstanceOf[A]
}
createNew[C1] //> its all ok
createNew[C2] //> its all ok
createNew[C3] //> crashes here; lets pretend we got C3 class
To use it with createOld, just pass implicit argument:
def createOld[A](c: Class[A])(implicit t: TypeTag[A]): A = createNew[A]
createOld[C1] //> its all ok
createOld[C2] //> its all ok
createOld[C3] //> crashes here; lets pretend we got C3 class
I think I should not tell you twice that it is not very good.
We can improve this code by using shapeless:
Lets create a poly function, which has a TypeTag as an argument:
import shapeless._; import scala.reflect.runtime.universe._;
def getTypeTag[T](implicit t: TypeTag[T]) = t //> to get TypeTag of a class
// here is low prority implicit
trait createPolyNewErr extends Poly1 {
implicit def newErr[T] = at[T](_ => "Error can not create object of this class")
}
object createPolyBew extends createPolyNewError {
implicit def newC1 = at[TypeTag[C1]](_ => new C1)
implicit def newC2 = at[TypeTag[C2]](_ => new C2)
}
createPolyNew(getTypeTag[C1]) //> success
createPolyNew(getTypeTag[C2]) //> success
createPolyNew(getTypeTag[C3]) //> String: Error can not create object of this class no crash!
We also can write a function, in order not to use function getTypeTag[T] every time:
def createPoly[T]
(implicit t: TypeTag[T],
cse: poly.Case[createPolyNew.type, TypeTag[T] :: HNil]) = cse(t)
createPoly[C1] //> its all ok
createPoly[C2] //> its all ok
createPoly[C3] //> String: Error can not create object of this class no crash!
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.
Suppose that I have the following scala code:
trait ValueSource[A] {
def value(a: Int): A
}
trait ValueSourceOps[A] {
def self: Int
def F: ValueSource[A]
def value: A = F.value(self)
}
trait ToValueSourceOps {
implicit def toValueSourceOps[A](index: Int)(implicit F0: ValueSource[A]): ValueSourceOps[A] = new ValueSourceOps[A] {
def self = index
def F: ValueSource[A] = F0
}
}
object Test extends ToValueSourceOps {
def value[A: ValueSource](index: Int): A = toValueSourceOps(index).value
}
The code above compiles well, but when I change the last line (body of method "value" in object Test) to
def value[A: ValueSource](index: Int): A = index.value
the compiler complains that
could not find implicit value for parameter F0: ValueSource[A]
In my opinion, def value[A: ValueSource] means I have a implicit value "ValueSource[A]", then why does the compilation fail?
The A in toValueSourceOps has no relationship with the A in value, which makes inferring it problematic. To me the real question is why it works when you call the method explicitly.
I'm guessing that, when toValueSourceOp is called explicitly, it has to infer the same A because that's the only implicit available.