I have been trying to marshal a bunch of Maps but I get error. Here is the definitions:
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._
import scala.collection.JavaConverters._
case class SchemaMap( schemaMap: scala.collection.immutable.Map[String, Integer] ) /** FIRST ERROR IS HERE!! **/
case class Profile( counts: scala.collection.immutable.Map[String, SchemaMap] )
case class Profiles( profiles: scala.collection.immutable.Seq[Profile] )
object Profiles {
implicit val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
implicit val profileMarshall = jsonFormat1(Profile.apply)
implicit val profilesMarshall = jsonFormat1(Profiles.apply)
def convertAProfileToScala(javaProfile: edu.illinois.cs.cogcomp.profilerNew.model.Profile): Profile = {
val out = javaProfile.getAllSchema.asScala.map{item =>
(item._1, SchemaMap(item._2.asScala.toMap))
}.toMap
Profile(out)
}
def convert[Profiles](sq: collection.mutable.Seq[Profiles]): collection.immutable.Seq[Profiles] =
collection.immutable.Seq[Profiles](sq:_*)
def convertProfilesToScala(javaProfiles: java.util.List[edu.illinois.cs.cogcomp.profilerNew.model.Profile]): Profiles = {
val a: collection.mutable.Seq[Profile] = javaProfiles.asScala.map{ convertAProfileToScala }
val immutableSeq = collection.immutable.Seq[Profile](a:_*)
Profiles(immutableSeq)
}
}
Here is the error:
Error:(16, 47) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,Integer]]
implicit val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
^
Error:(16, 47) not enough arguments for method jsonFormat1: (implicit evidence$1: spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,Integer]], implicit evidence$2: ClassManifest[org.allenai.example.webapp.SchemaMap])spray.json.RootJsonFormat[org.allenai.example.webapp.SchemaMap].
Unspecified value parameters evidence$1, evidence$2.
implicit val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
^
Error:(17, 45) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,org.allenai.example.webapp.SchemaMap]]
implicit val profileMarshall = jsonFormat1(Profile.apply)
^
Error:(17, 45) not enough arguments for method jsonFormat1: (implicit evidence$1: spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,org.allenai.example.webapp.SchemaMap]], implicit evidence$2: ClassManifest[org.allenai.example.webapp.Profile])spray.json.RootJsonFormat[org.allenai.example.webapp.Profile].
Unspecified value parameters evidence$1, evidence$2.
implicit val profileMarshall = jsonFormat1(Profile.apply)
^
Error:(18, 46) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Seq[org.allenai.example.webapp.Profile]]
implicit val profilesMarshall = jsonFormat1(Profiles.apply)
^
Error:(18, 46) not enough arguments for method jsonFormat1: (implicit evidence$1: spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Seq[org.allenai.example.webapp.Profile]], implicit evidence$2: ClassManifest[org.allenai.example.webapp.Profiles])spray.json.RootJsonFormat[org.allenai.example.webapp.Profiles].
Unspecified value parameters evidence$1, evidence$2.
implicit val profilesMarshall = jsonFormat1(Profiles.apply)
^
NOTE: there is a similar post here, but the answer didn't help here. As you can see I already have the imports suggested in its answer and have all the variables immutable.
One error at a time. The problem here is that your map is using Integer, which Spray doesn't know how to map. If you use Int then it will work:
scala> case class SchemaMap( schemaMap: scala.collection.immutable.Map[String, Integer] )
defined class SchemaMap
scala> val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
<console>:12: error: could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,Integer]]
scala> case class SchemaMap( schemaMap: scala.collection.immutable.Map[String, Int])
defined class SchemaMap
scala> val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
schemaMapMarshall: spray.json.RootJsonFormat[SchemaMap] = spray.json.ProductFormatsInstances$$anon$1#53e166ad
Alternately you can define your own JsonFormat[Integer].
Related
Ultimately what I want to do is provide one implementation of a type class for some specific type T and another implementation for all other types which are not T. I thought (perhaps incorrectly) that the easiest way to do this would be to try type negation via ambiguous implicits as described in this question. However, if I accidentally omit the implicit type class declaration, my code will still compile (should it?) but include bugs as only one of the implementations is used.
This is how the context bound is defined:
scala> trait NotAnInt[A]
defined trait NotAnInt
scala> implicit def everythingIsNotAnInt[A]: NotAnInt[A] = new NotAnInt[A] {}
everythingIsNotAnInt: [A]=> NotAnInt[A]
scala> implicit def intsAreInts1: NotAnInt[Int] = ???
intsAreInts1: NotAnInt[Int]
scala> implicit def intsAreInts2: NotAnInt[Int] = ???
intsAreInts2: NotAnInt[Int]
scala> implicit def nothingsAreInts1: NotAnInt[Nothing] = ???
nothingsAreInts1: NotAnInt[Nothing]
scala> implicit def nothingsAreInts2: NotAnInt[Nothing] = ???
nothingsAreInts2: NotAnInt[Nothing]
At this point NotAnInt[T] is summonable for all T except Int/Nothing:
scala> implicitly[NotAnInt[String]]
res3: NotAnInt[String] = $anon$1#1a24fe09
scala> implicitly[NotAnInt[Int]]
<console>:16: error: ambiguous implicit values:
both method intsAreInts1 of type => NotAnInt[Int]
and method intsAreInts2 of type => NotAnInt[Int]
match expected type NotAnInt[Int]
implicitly[NotAnInt[Int]]
^
scala> implicitly[NotAnInt[Nothing]]
<console>:18: error: ambiguous implicit values:
both method nothingsAreInts1 of type => NotAnInt[Nothing]
and method nothingsAreInts2 of type => NotAnInt[Nothing]
match expected type NotAnInt[Nothing]
implicitly[NotAnInt[Nothing]]
^
Now I have my NotAnInt context bound defined I can create my type class with its implementations:
scala> trait IntChecker[A] { def isInt(): Boolean }
defined trait IntChecker
scala> implicit val intIntChecker: IntChecker[Int] = new IntChecker[Int] { override def isInt = true }
intIntChecker: IntChecker[Int] = $anon$1#585dd35c
scala> implicit def otherIntChecker[A: NotAnInt]: IntChecker[A] = new IntChecker[A] { override def isInt = false }
otherIntChecker: [A](implicit evidence$1: NotAnInt[A])IntChecker[A]
This type class can be used as expected:
scala> def printIntStatus[T: IntChecker](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatus: [T](t: T)(implicit evidence$1: IntChecker[T])Unit
scala> printIntStatus(3)
true
scala> printIntStatus("three")
false
However, the following also compiles:
scala> def printIntStatusWithBug[T](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatusWithBug: [T](t: T)Unit
scala> printIntStatusWithBug(3)
false
scala> printIntStatusWithBug("three")
false
I would not expect this second function to compile as there should be no implicit IntChecker[T] available. I expect everythingIsNotAnInt is the cause of this problem but I can't think of a way around this.
I'm interested in why this approach fails as well as alternative methods on how to achieve the same thing. Thank you.
Consider the following alternative implementation (which uses Sabin's type inequalities)
trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null
trait IntChecker[A] {
def isInt(): Boolean
}
object IntChecker {
import scala.reflect.ClassTag
implicit val intIntChecker: IntChecker[Int] = () => true
implicit def notIntIntChecker[T: ClassTag](implicit ev: T =!= Int): IntChecker[T] = () => false
}
def printIntStatus[T: IntChecker](t: T) = implicitly[IntChecker[T]].isInt()
import IntChecker._
printIntStatus(3)
printIntStatus("three")
which outputs
res0: Boolean = true
res1: Boolean = false
however the buggy implementation where we forget IntChecker bound
def printIntStatusWithBug[T](t: T) = implicitly[IntChecker[T]].isInt()
should not compile due to having T: ClassTag bound in
implicit def notIntIntChecker[T: ClassTag](implicit ev: T =!= Int)
giving compiler error
could not find implicit value for parameter e: IntChecker[T]
def printIntStatusWithBug[T](t: T) = implicitly[IntChecker[T]].isInt()
^
Can someone please explain to me why I get a 'diverging implicit expansion error' here? I think it has to do with the type synonym type MyIdType = String but I am not sure why.
import org.scalacheck.Arbitrary
import org.scalacheck.Arbitrary._
import org.scalacheck.Gen
def arbitraryCaseClass[A,C](f: A => C)(implicit t: Arbitrary[A]): Arbitrary[C] = Arbitrary(for(v <- arbitrary[A]) yield f(v))
type MyIdType = String
implicit val arbMyIdType: Arbitrary[MyIdType] = Arbitrary(Gen.identifier)
case class Foo(s: MyIdType, t: Int)
implicit def arbA = arbitraryCaseClass((Foo.apply _).tupled)
val foo = arbitrary[Foo].sample
error:
Error:(13, 40) diverging implicit expansion for type org.scalacheck.Arbitrary[(A$A6.this.MyIdType, Int)]
starting with method arbTuple2 in trait ArbitraryArities
implicit def arbA = arbitraryCaseClass((Foo.apply _).tupled)
Here's the code,
trait TestBase{}
class TestA(str:String) extends TestBase
class TestB(str:String) extends TestBase
class TestC(str:String) extends TestBase
implicit def mystr2TestA(str:String):TestA = {println(str);null.asInstanceOf[TestA]}
implicit def mystr2TestB(str:String):TestB = {println(str);null.asInstanceOf[TestB]}
implicit def mystr2TestC(str:String):TestC = {println(str);null.asInstanceOf[TestC]}
val testA:TestA = "abc"
val testB:TestB = "abc"
val testC:TestC = "abc"
Question is how to create the implicit conversion from String to TestBase and its subclass with more elegant and efficient code?(Maybe just one implicit function?) This is the Code I run in Scala REPL
You could rewrite this as one implicit def like this.
implicit def conv[A <: TestBase](str: String): A = {println(str); null.asInstanceOf[A] }
But depending on what you are really trying to, there might be a better solution than converting all Strings to any TestBase.
EDIT:
For some reason Scala doesn't seem to consider the type constraint when selecting the implicit conversion. It gets even weirder:
scala> implicit def bla2Test[A](str: String)(implicit ev: A <:< TestBase): A = null.asInstanceOf[A]
warning: there were 1 feature warning(s); re-run with -feature for details
bla2Test: [A](str: String)(implicit ev: <:<[A,TestBase])A
scala> val notTest: NotTest = "str"
notTest: NotTest = null
scala> implicitly[NotTest <:< TestBase]
<console>:15: error: Cannot prove that NotTest <:< TestBase.
implicitly[NotTest <:< TestBase]
^
So the compiler supplies an instance of NotTest <:< TestBase to bla2Test but no instance exists.
And when you want to inspect the type A:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> implicit def bla2Test[A <: TestBase](str: String)(implicit tag: TypeTag[A]): A = { println(tag); null.asInstanceOf[A] }
warning: there was one feature warning; re-run with -feature for details
bla2Test: [A <: TestBase](str: String)(implicit tag: reflect.runtime.universe.TypeTag[A])A
scala> val notTest: NotTest = "str"
<console>:21: error: type mismatch;
found : String("str")
required: NotTest
val notTest: NotTest = "str"
^
scala> val notTest: TestBase = "str"
<console>:20: error: macro has not been expanded
val notTest: TestBase = "str"
^
Consider the following (working) snippet that defines bidirectional implicit conversions between the DenseVector and Arrays:
import scala.reflect.ClassTag
import org.apache.spark.mllib.linalg.Vectors
import breeze.linalg.{DenseVector => BDV}
implicit def bdvToSeq[T](vect: BDV[T])(implicit ct: ClassTag[T]): Seq[T] = vect.toArray.toSeq
implicit def arrayToVect(darr: Array[Double]): BDV[Double]
= new BDV(darr)
implicit def bdvToArray[T](vect: BDV[T])(implicit ct: ClassTag[T]): Array[T] = vect.toArray
def add(v1: BDV[Double], v2: BDV[Double]) =
v1.zip(v2).map { x => x._1 + x._2}
Let's try it out:
scala> arr.allVisitableIndicesActive // Array to DenseVector implicit conversion
res4: Boolean = true
scala> val d = new BDV(Array(77.7, 88.8, 99.9))
d: breeze.linalg.DenseVector[Double] = DenseVector(77.7, 88.8, 99.9)
Now the other direction:
scala> def myArrMethod(arr: Array[Double]) = println(arr.mkString(","))
myArrMethod: (arr: Array[Double])Unit
scala> myArrMethod(d) // DenseVector to array conversion
77.7,88.8,99.9
The following also works: notice the darr.toSeq
def norm(darr: Array[Double]): Double = {
Math.sqrt(darr.toSeq.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
}
However if we omit the .toSeq then we have implicits collision:
scala> def norm(darr: Array[Double]): Double = {
Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
}
<console>:34: error: type mismatch;
found : darr.type (with underlying type Array[Double])
required: ?{def foldLeft(x$1: ? >: Double(0.0)): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method doubleArrayOps in object Predef of type (xs: Array[Double])scala.collection.mutable.ArrayOps[Double]
and method arrayToVect of type (darr: Array[Double])breeze.linalg.DenseVector[Double]
are possible conversion functions from darr.type to ?{def foldLeft(x$1: ? >: Double(0.0)): ?}
Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
^
<console>:34: error: value foldLeft is not a member of Array[Double]
Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
I would however prefer not to put the ".toSeq" explicitly.
So my question is: how to set the proper precedence so that the Predef.toSeq is the clear winner - always tried before the custom lower priority implicits defined above?
You can extract all your implicit conversions into object, and import them only where needed
trait BDVImplicits {
implicit def bdvToSeq[T](vect: BDV[T])(implicit ct: ClassTag[T]): Seq[T] =
vect.toArray.toSeq
implicit def arrayToVect(darr: Array[Double]): BDV[Double] =
new BDV(darr)
implicit def bdvToArray[T](vect: BDV[T])(implicit ct: ClassTag[T]): Array[T] =
vect.toArray
}
object BDVImplicits extends BDVImplicits
If you'll place your 'norm' method in Utils for example, and don't import implicit you'll be good. You'll just need to import BDVImplicits._ in class where you call your Util methods.
I think it's simplest workaround for this problem.
I'm playing around with Scalas new macros and found this gist from akshaal. As it seams I did not quite get it.
Given the following trait (the fieldsMacro is more or less the same as in akshaal example)
case class Field[I <: AnyRef](name: String, get: I => Any)
type Fields[I <: AnyRef] = List[Field[I]]
trait FieldAccess {
import FieldMacors._
import Field._
import language.experimental.macros
def fields[T <: AnyRef]: Fields[T] = macro fieldsMacro[T]
def field[T <: AnyRef](name: String): Fields[T] = fields[T].headOption <-- does not work!
^
}
object FieldMacors {
import language.experimental.macros
import Field._
def fields[T <: AnyRef]: Fields[T] = macro fieldsMacro[T]
/**
* Get a list of fiels
*/
def fieldsMacro[T <: AnyRef: c.TypeTag](c: Context): c.Expr[Fields[T]] = {
import c.universe._
val instanceT = c.typeOf[T]
val fields = instanceT.members.filter(member => member.isTerm && !member.isMethod)
// transform an iterable of expr in a expr of list.
def foldIntoListExpr[T: c.TypeTag](exprs: Iterable[c.Expr[T]]): c.Expr[List[T]] =
exprs.foldLeft(reify { Nil: List[T] }) {
(accumExpr, expr) =>
reify { expr.splice :: accumExpr.splice }
}
val fieldAccessores = for (field <- fields) yield {
val name = field.name.toString.trim // Why is there a space at the end of field name?!
val nameExpr = c literal name
// Construct expression (x : $I) => x.$name
val getFunArgTree = ValDef(Modifiers(), newTermName("x"), TypeTree(instanceT), EmptyTree)
val getFunBodyTree = Select(Ident(newTermName("x")), newTermName(name))
val getFunExpr = c.Expr[T => Any](Function(List(getFunArgTree), getFunBodyTree))
reify {
Field[T](name = nameExpr.splice, get = getFunExpr.splice)
}
}
foldIntoListExpr(fieldAccessores)
}
}
the compiler complains about
'Cannot create TypeTag from a type T having unresolved type parameters'
How do I manage to get the T to the macro or must I implement another macro that uses the fieldsMacro
T: TypeTag context bound for a type parameter T means that you require type arguments provided in place of this parameter to be concrete (i.e. not contain references to untagged type parameters or abstract type members). Otherwise an error occurs.
Examples:
scala> val ru = scala.reflect.runtime.universe
ru # 6d657803: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse#6d657803
scala> def foo[T: ru.TypeTag] = implicitly[ru.TypeTag[T]]
foo: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]
scala> foo[Int]
res0 # 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]
scala> foo[List[Int]]
res1 # 7d53ccbe: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
scala> def bar[T] = foo[T] // T is not a concrete type here, hence the error
<console>:26: error: No TypeTag available for T
def bar[T] = foo[T]
^
scala> def bar[T] = foo[List[T]] // T being not concrete renders
// the entire compound type not concrete
<console>:26: error: No TypeTag available for List[T]
def bar[T] = foo[List[T]]
^
scala> def bar[T: TypeTag] = foo[T] // to the contrast T is concrete here
// because it's bound by a concrete tag bound
bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]
scala> bar[Int]
res2 # 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]
scala> def bar[T: TypeTag] = foo[List[T]]
bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[List[T]]
scala> bar[Int]
res3 # 1a108c98: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
scala> bar[List[Int]]
res4 # 76d5989c: reflect.runtime.universe.TypeTag[List[List[Int]]] = TypeTag[scala.List[scala.List[Int]]]
Having a notion of concrete types to be enforcible at compile-time is useful. Having concrete type tags on by default is useful as well as described in https://issues.scala-lang.org/browse/SI-5884.
However as you've seen yourself, concrete type tags in macros can be a source of confusion, because typically macros should work both for concrete and non-concrete types. Therefore one should always use c.AbsTypeTag instead. Due to this reason we no longer allow c.TypeTag context bounds in 2.10.0-M7: https://github.com/scala/scala/commit/788478d3ab.
Edit. In 2.10.0-RC1 some AbsTypeTag has been renamed to WeakTypeTag. Everything else about type tags remains the same.