The compiler keeps producing the following errors:
No ClassTag available for a
val keys = Array.fill(maxSize+1){ default[a] }
^
not enough arguments for method fill: (implicit evidence$9: scala.reflect.ClassTag[a])Array[a].
Unspecified value parameter evidence$9.
val keys = Array.fill(maxSize+1){ default[a] }
^
for this piece of code
object Utils {
def default[a] = {
class DefaultVal {
var x: a = _
}
(new DefaultVal).x
}
}
class IndexedHeap[a](maxSize: Int)(implicit ev: Ordering[a]) {
import ev._
import Utils._
val keys = Array.fill(maxSize+1){ default[a] }
}
Any ideas on how to fix this?
I think adding ClassTag would fix it, like this:
[a:ClassTag]
edit based on your comment on the conflict with implicit params and context bounds:
Change the implicit parameters to include the ClassTag too
implicit ev: Ordering[a], ct: ClassTag[a]
Related
I wrote a macros, that reads class fields:
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object ArrayLikeFields {
def extract[T]: Set[String] = macro extractImpl[T]
def extractImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[Set[String]] = {
import c.universe._
val tree = weakTypeOf[T].decls
.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor => m
}
.map(y => y.paramLists.headOption.getOrElse(Seq.empty))
.getOrElse(Seq.empty)
.map(s => q"${s.name.decodedName.toString}")
c.Expr[Set[String]] {
q"""Set(..$tree)"""
}
}
}
I'm able to compile and run it for concrete type:
object Main extends App {
case class Person(name:String)
val res: Set[String] = ArrayLikeFields.extract[Person]
}
But i want use it with generic types like that:
object Lib {
implicit class SomeImplicit(s: String) {
def toOrgJson[T]: JSONObject = {
val arrayLikeFields: Set[String] = ArrayLikeFields.extract[T]
//some code, that uses fields, etc
null
}
}
}
Compilation error:
Error:(14, 65) type mismatch; found :
scala.collection.immutable.Set[Nothing] required: Set[String] Note:
Nothing <: String, but trait Set is invariant in type A. You may wish
to investigate a wildcard type such as _ <: String. (SLS 3.2.10)
val arrayLikeFields: Set[String] = ArrayLikeFields.extract[T]
I can't understund that. How can I solve my problem?
upd
I read scala 2.10.2 calling a 'macro method' with generic type not work about materialisation, but i have no instance of class
Try approach with materializing a type class like in 1
object Main extends App {
case class Person(name:String)
val res: Set[String] = ArrayLikeFields.extract[Person] //Set(name)
import Lib._
"abc".toOrgJson[Person] // prints Set(name)
}
object Lib {
implicit class SomeImplicit(s: String) {
def toOrgJson[T: ArrayLikeFields.Extract]: JSONObject = {
val arrayLikeFields: Set[String] = ArrayLikeFields.extract[T]
//some code, that uses fields, etc
println(arrayLikeFields) //added
null
}
}
}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object ArrayLikeFields {
def extract[T](implicit extr: Extract[T]): Set[String] = extr()
trait Extract[T] {
def apply(): Set[String]
}
object Extract {
implicit def materializeExtract[T]: Extract[T] = macro materializeExtractImpl[T]
def materializeExtractImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[Extract[T]] = {
import c.universe._
val tree = weakTypeOf[T].decls
.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor => m
}
.map(y => y.paramLists.headOption.getOrElse(Seq.empty))
.getOrElse(Seq.empty)
.map(s => q"${s.name.decodedName.toString}")
c.Expr[Extract[T]] {
q"""new ArrayLikeFields.Extract[${weakTypeOf[T]}] {
override def apply(): _root_.scala.collection.immutable.Set[_root_.java.lang.String] =
_root_.scala.collection.immutable.Set(..$tree)
}"""
}
}
}
}
Actually, I don't think you need whitebox macros here, blackbox ones should be enough. So you can replace (c: whitebox.Context) with (c: blackbox.Context).
By the way, the same problem can be solved with Shapeless rather than macros (macros work in Shapeless under the hood)
object Main extends App {
case class Person(name:String)
val res: Set[String] = ArrayLikeFields.extract[Person] //Set(name)
}
object ArrayLikeFields {
def extract[T: Extract]: Set[String] = implicitly[Extract[T]].apply()
trait Extract[T] {
def apply(): Set[String]
}
object Extract {
def instance[T](strs: Set[String]): Extract[T] = () => strs
implicit def genericExtract[T, Repr <: HList](implicit
labelledGeneric: LabelledGeneric.Aux[T, Repr],
extract: Extract[Repr]
): Extract[T] = instance(extract())
implicit def hconsExtract[K <: Symbol, V, T <: HList](implicit
extract: Extract[T],
witness: Witness.Aux[K]
): Extract[FieldType[K, V] :: T] =
instance(extract() + witness.value.name)
implicit val hnilExtract: Extract[HNil] = instance(Set())
}
}
The answer on the linked question, scala 2.10.2 calling a 'macro method' with generic type not work , also applies here.
You are trying to solve a run-time problem with a compile-time macro, which is not possible.
The called method toOrgJson[T] cannot know the concrete type that T represents at compile time, but only gets that information at run-time. Therefore, you will not be able to do any concrete operations on T (such as listing its fields) at compile-time, only at run-time.
You can implement an operation like ArrayLikeFields.extract[T] at run-time using Reflection, see e.g. Get field names list from case class
I don't have a very solid understanding of Macros, but it seems that the compiler does not understand that the return type of the macro function is Set[String].
The following trick worked for me in scala 2.12.7
def toOrgJson[T]: JSONObject = {
val arrayLikeFields: Set[String] = ArrayLikeFields.extract[T].map(identity[String])
//some code, that uses fields, etc
null
}
EDIT
Actually to get a non empty Set T needs an upper bound such as T <: Person... and that is not what you wanted...
Leaving the answer here since the code does compile, and it might help someone in the direction of an answer
I want to be able to dynamically choose which extractors to use in my case class pattern matching.
I want something like:
def handleProcessingResult(extract: SomeType) : PartialFunction[Event, State] = {
case Event(someEvent: SomeEvent, extract(handlers)) =>
...
case Event(otherEvent: OtherEvent, extract(handlers)) =>
...
}
The idea is that I can have the above partial function, and can then use it anywhere where I know how to write an unapply to match and extract handlers from some pattern matched type.
If you are wondering why I want these partial functions, it is so that I can compose partial functions of common behaviour together to form the handlers for my states in an Akka FSM. This is not required to understand the question, but for example:
when(ProcessingState) {
handleProcessingResult(extractHandlersFromProcessing) orElse {
case Event(Created(path), Processing(handlers)) =>
...
}
}
when(SuspendedState) {
handleProcessingResult(extractHandlersFromSuspended) orElse {
case Event(Created(path), Suspended(waiting, Processing(handlers))) =>
...
}
It seems like this should be possible but I can't figure out how!
I have tried the following two simplifications:
object TestingUnapply {
sealed trait Thing
case class ThingA(a: String) extends Thing
case class ThingB(b: String, thingA: ThingA) extends Thing
val x = ThingA("hello")
val y = ThingB("goodbye", ThingA("maybe"))
process(x, new { def unapply(thing: ThingA) = ThingA.unapply(thing)})
process(y, new { def unapply(thing: ThingB) = ThingB.unapply(thing).map(_._2.a)})
def process(thing: Thing, extract: { def unapply[T <: Thing](thing: T): Option[String]}) = thing match {
case extract(a) => s"The value of a is: $a"
}
}
The idea being that I should be able to pass any sub-type of Thing and a suitable extractor to process. However, it doesn't compile due to:
[error] /tmp/proj1/TestUnapply.scala:10: type mismatch;
[error] found : AnyRef{def unapply(thing: TestingUnapply.ThingA): Option[String]}
[error] required: AnyRef{def unapply[T <: TestingUnapply.Thing](thing: T): Option[String]}
[error] process(x, new { def unapply(thing: ThingA) = ThingA.unapply(thing)})
[error] ^
[error] /tmp/proj1/TestUnapply.scala:11: type mismatch;
[error] found : AnyRef{def unapply(thing: TestingUnapply.ThingB): Option[String]}
[error] required: AnyRef{def unapply[T <: TestingUnapply.Thing](thing: T): Option[String]}
[error] process(y, new { def unapply(thing: ThingB) = ThingB.unapply(thing).map(_._2.a)})
[error] ^
Subsequently, moving the declaration of type parameter T onto process, gives us:
import scala.reflect.ClassTag
object TestingUnapply {
sealed trait Thing
case class ThingA(a: String) extends Thing
case class ThingB(b: String, thingA: ThingA) extends Thing
val x = ThingA("hello")
val y = ThingB("goodbye", ThingA("maybe"))
process(x, new { def unapply(thing: ThingA) = ThingA.unapply(thing)})
process(y, new { def unapply(thing: ThingB) = ThingB.unapply(thing).map(_._2.a)})
def process[T <: Thing: ClassTag](thing: Thing, extract: { def unapply(thing: T): Option[String]}) = thing match {
case extract(a) => s"The value of a is: $a"
}
}
Now gives us a different compilation error of:
[error] /tmp/TestUnapply.scala:18: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
[error] def process[T <: Thing: ClassTag](thing: Thing, extract: { def unapply(thing: T): Option[String]}) = thing match {
I am most likely doing something daft. Can someone help me please?
Try to make an workaround based on your first simplification, hope it helps.
object DynamicPattern extends App {
sealed trait Thing
case class ThingA(a: String) extends Thing
case class ThingB(b: String, thingA: ThingA) extends Thing
// change structural type to an abstract class
abstract class UniversalExtractor[T <: Thing] {
def unapply(thing: T): Option[String]
}
// extract is an instance of UniversalExtractor with unapply method
// naturally it's an extractor
def process[T <: Thing](thing: T, extract: UniversalExtractor[T]) =
thing match {
case extract(a) => s"The value of a is: $a"
}
val x = ThingA("hello")
val y = ThingB("goodbye", ThingA("maybe"))
val result1 = process(
x,
new UniversalExtractor[ThingA] {
def unapply(thing: ThingA) = ThingA.unapply(thing)
}
)
val result2 = process(y,
new UniversalExtractor[ThingB] {
def unapply(thing: ThingB) = ThingB.unapply(thing).map(_._2.a)
}
)
// result1 The value of a is: hello
println(" result1 " + result1)
// result2 The value of a is: maybe
println(" result2 " + result2)
}
Update
A probably "nasty" method without using an abstract class or trait hinted by the type conformance problem I explained later.
// when invoking process method, we actually know which subtype of
// Thing is pattern-matched, plus the type conformance problem,
// so here comes the ```unapply[T <: Thing](thing: T)```
// and ```asInstanceOf(which is usually not that appealing)```.
val thingAExtractor = new {
def unapply[T <: Thing](thing: T): Option[String] =
ThingA.unapply(thing.asInstanceOf[ThingA])
}
val thingBExtractor = new {
def unapply[T <: Thing](thing: T): Option[String] =
ThingB.unapply(thing.asInstanceOf[ThingB]).map(_._2.a)
}
// hello
println(process(x, thingAExtractor))
// maybe
println(process(y, thingBExtractor))
The reason it doesn't work in the two simplifications(actually the nasty method just pops up in my mind when I try to figure out the reason, so just write it here in case it helps).
For the first simplication: it's about the type conformance problem.
type ExtractType = { def unapply[T <: Thing](thing: T): Option[String] }
val anonExtractor = new { def unapply(thing: ThingA) = ThingA.unapply(thing) }
import scala.reflect.runtime.{ universe => ru }
import scala.reflect.runtime.universe.{ TypeTag, typeTag }
def getTypeTag[T: TypeTag](o: T) = typeTag[T].tpe
def getTypeTag[T: TypeTag] = ru.typeOf[T]
// false | so in turn type check fails at compilation time
println(getTypeTag(anonExtractor) <:< getTypeTag[ExtractType])
ScalaDoc Reflection's Runtime Classes in Java vs. Runtime Types in Scala part demonstrates the type conformance in similar case. In short, Scala compiler creates synthetic classes that are used at runtime in place of user-defined classes to be translated to equivalent Java Bytecode in cases mentioned in that part.
For the second simplication: this post parameter-type-in-structural-refinement-may-not-refer-to-an-abstract-type-define-outside has given some detailed explanation.
I'm trying to add an implicit value to (what I believe is) the companion object of a case class, but this implicit value is not found.
I'm trying to achieve something like the following:
package mypackage
object Main {
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = ...
serialize(out, caseClassInstance)
// the above line makes the compiler complain that there is no
// Serializer[MyCaseClass] in scope
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
...
}
}
object MyCaseClass {
// implicits aren't found here
implicit val serializer: Serializer[MyCaseClase] = ...
}
case class MyCaseClass(s: String) {
// some other methods
}
I've explicitly added the package here to show that both the MyCaseClass case class and object should be in scope. I know that the object is actually being constructed because I can get this to compile if I add
implicit val serializer = MyCaseClass.serializer
to main (though notably not if I add import MyCaseClass.serializer).
I'm concerned that the MyCaseClass object is not actually a companion of the case class, because if I explicitly define apply and unapply on the object and then attempt to call MyCaseClass.apply("string") in main, the compiler gives the following error:
ambiguous reference to overloaded definition,
both method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
and method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
match argument types (String)
val a = InputRecord.apply("string")
^
If it's not possible to take this approach, is there a way to use type classes with case classes without creating an implicit value every time it must be brought into scope?
EDIT: I'm using scala 2.10.3.
EDIT 2: Here's the example fleshed out:
package mypackage
import java.io.{DataOutput, DataOutputStream}
object Main {
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = new DataOutputStream(System.out)
serialize(out, caseClassInstance)
// the above line makes the compiler complain that there is no
// Serializer[MyCaseClass] in scope
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
implicitly[Serializer[T]].write(out, t)
}
}
object MyCaseClass {
// implicits aren't found here
implicit val serializer: Serializer[MyCaseClass] = new Serializer[MyCaseClass] {
override def write(out: DataOutput, t: MyCaseClass): Unit = {
out.writeUTF(t.s)
}
}
}
case class MyCaseClass(s: String) {
// some other methods
}
trait Serializer[T] {
def write(out: DataOutput, t: T): Unit
}
This actually compiles, though. I am getting this issue when using Scoobi's WireFormat[T] instead of Serializer, but can't provide a concise, runnable example due to complexity and the Scoobi dependency. I will try to create a more relevant example, but it seems as though the issue is not as general as I thought.
It turns out that the type class instances actually need to be implicit values, rather than objects. The MyCaseClass object above works because its serializer is assigned to an implicit value. However, this implementation
object MyCaseClass {
implicit object MyCaseClassSerializer extends Serializer[MyCaseClass] {
override def write(out: DataOutput, t: MyCaseClass): Unit = {
out.writeUTF(t.s)
}
}
}
fails with the error
Main.scala:9: error: could not find implicit value for evidence parameter of type mypackage.Serializer[mypackage.MyCaseClass]
serialize(out, caseClassInstance)
^
In my real code, I was using an auxiliary function to generate the Serializer[T] (see https://github.com/NICTA/scoobi/blob/24f48008b193f4e87b9ec04d5c8736ce0725d006/src/main/scala/com/nicta/scoobi/core/WireFormat.scala#L137). Despite the function having its own explicit return type, the type of the assigned value was not being inferred correctly by the compiler.
Below is the full example from the question with such a Serializer-generator.
package mypackage
import java.io.{DataOutput, DataOutputStream}
object Main {
import Serializer._
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = new DataOutputStream(System.out)
serialize(out, caseClassInstance)
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
implicitly[Serializer[T]].write(out, t)
}
}
object MyCaseClass {
import Serializer._
// does not compile without Serializer[MyCaseClass] type annotation
implicit val serializer: Serializer[MyCaseClass] =
mkCaseSerializer(MyCaseClass.apply _, MyCaseClass.unapply _)
}
case class MyCaseClass(s: String)
trait Serializer[T] {
def write(out: DataOutput, t: T): Unit
}
object Serializer {
// does not compile without Serializer[String] type annotation
implicit val stringSerializer: Serializer[String] = new Serializer[String] {
override def write(out: DataOutput, s: String): Unit = {
out.writeUTF(s)
}
}
class CaseClassSerializer[T, A : Serializer](
apply: A => T, unapply: T => Option[A]) extends Serializer[T] {
override def write(out: DataOutput, t: T): Unit = {
implicitly[Serializer[A]].write(out, unapply(t).get)
}
}
def mkCaseSerializer[T, A : Serializer]
(apply: A => T, unapply: T => Option[A]): Serializer[T] =
new CaseClassSerializer(apply, unapply)
}
This related, simple code below prints 1.
object A{
implicit def A2Int(a:A)=a.i1
}
case class A(i1:Int,i2:Int)
object Run extends App{
val a=A(1,2)
val i:Int=a
println(i)
}
I have some code like this:
class ReflectiveJsonFormat[T:TypeTag] extends JsonFormat[T] {
def write(x: T) : JsValue = {
val t = typeOf[T]
val getters = t.declarations.filter { s => s.isMethod && s.asMethod.isGetter }
val mirror = runtimeMirror(this.getClass.getClassLoader)
val instanceMiror = mirror.reflect(x)
}
}
That last line fails with:
No ClassTag available for T
I thought TypeTag was more info than a ClassTag? Can I get the ClassTag from the TypeTag? If not, is there some syntax for saying that T has two context bounds -- both TypeTag and ClassTag? Or, how would you otherwise fix this code?
The library doesn't provide a built-in method that directly converts a TypeTag to a ClassTag, but you can write one:
import reflect.runtime.universe._
import reflect.ClassTag
def typeToClassTag[T: TypeTag]: ClassTag[T] = {
ClassTag[T]( typeTag[T].mirror.runtimeClass( typeTag[T].tpe ) )
}
Then in your method just add before the implicit ClassTag is needed:
implicit val c = typeToClassTag[T]
Well scala does support multiple context bounds if that is what you are after:
class ReflectiveJsonFormat[T:TypeTag:ClassTag]
I'm trying to find the most convenient way to normalize the error types in a for-comprehension on scalaz.Validations in one "upper" layer that calls into methods returning Validations with differing error types on "lower" layers. Naturally there needs to be defined a mapping for each lower-level error type to an upper-layer error type but I cannot seem to get around providing explicit type-hints within the for comprehensions for my implicits to be picked up. I'd like to leave each line of the for-comprehension clean of explicit conversion of the error type (e.g. through .fail.map(...).validation. I tried an approach with an IsUpperError type-trait and an implicit conversion as follows:
package errorhandling
import scalaz._
import Scalaz._
class LowerServiceA {
def doStuff(): Validation[LowerServiceAError, Int] = Success(1)
}
sealed trait LowerServiceAError
// ... more specific error types
class LowerServiceB {
def doStuff(): Validation[LowerServiceBError, Int] = Success(1)
}
sealed trait LowerServiceBError
// ... more specific error types
class LowerServiceC {
def doStuff(): Validation[LowerServiceCError, Int] = Success(1)
}
sealed trait LowerServiceCError
// ... more specific error types
sealed trait UpperError {}
// ... more specific error types
trait IsUpperError[E] {
def apply(e: E): UpperError
}
object IsUpperError {
implicit val lowerServiceAErrorIsUpperError: IsUpperError[LowerServiceAError] = new IsUpperError[LowerServiceAError] {
def apply(err: LowerServiceAError) = new UpperError {}
}
implicit val lowerServiceBErrorIsUpperError: IsUpperError[LowerServiceBError] = new IsUpperError[LowerServiceBError] {
def apply(err: LowerServiceBError) = new UpperError {}
}
implicit val lowerServiceCErrorIsUpperError: IsUpperError[LowerServiceCError] = new IsUpperError[LowerServiceCError] {
def apply(err: LowerServiceCError) = new UpperError {}
}
}
object UpperError {
implicit def upperError[E: IsUpperError, A](v: Validation[E, A]): Validation[UpperError, A] =
v.fail.map(e => implicitly[IsUpperError[E]].apply(e)).validation
}
class UpperService(serviceA: LowerServiceA, serviceB: LowerServiceB, serviceC: LowerServiceC) {
def doStuff(): Validation[UpperError, Int] = {
for {
// I'd like to avoid the repeated type-hints or .fail.map(...).validation here
a <- serviceA.doStuff() // : Validation[UpperError, Int]
b <- serviceB.doStuff() // : Validation[UpperError, Int]
c <- serviceC.doStuff()
} yield a + b + c
}
}
The compiler error (2.9.2) without the type-hints:
ErrorHandling.scala:56: error: could not find implicit value for evidence parameter of type errorhandling.IsUpperError[java.lang.Object]
b <- serviceB.doStuff() //: Validation[UpperError, Int]
^
one error found
I'd also appreciate guidance if the desire to do this kind of thing hints at a problem in how I approach this kind of error-handling.