implicit value not applied in scope - scala

i'm trying to import a implicit Write declaration from an embedded object into a function that produces a JSON object based on a set of case classes.
case class TestModel(test:String)
object TestModel {
def manyToJSON(models: List[TestModel]) = {
import writes.micro
Json.toJson(models)
}
object writes {
implicit val micro = Json.writes[TestModel]
}
}
unfortunately, the scala compiler complains:
No Json serializer found for type List[models.TestModel]. Try to implement an implicit Writes or Format for this type.
the fun part is, if i'm using the write object as a pure expression within the method, its working.
object TestModel {
def manyToJSON(models: List[TestModel]) = {
import writes.micro
writes.micro
Json.toJson(models)
}
object writes {
implicit val micro = Json.writes[TestModel]
}
}
how would i have to change my code to have the implicit in scope?

the reason case class implicit is not working is that it is just a definition not value. Use case object will solve this issue like object. Consider this code:
object MainClass {
def main(args: Array[String]) {
TestModel.manyToJSON(Nil)
}
}
case class TestModel(test:String)
object TestModel {
def manyToJSON(models: List[TestModel]) = {
import writes._
def print(implicit x: Int) = {
println(x)
}
print // print 3
}
object writes {
implicit val x: Int = 3
//implicit val x = 3 //compilation error
}
}

Related

using enumeratum enum as BSONDocument value does not compile

when I try to wrap my query in BSONDocument and putting my enumeratum enum as the value it docent compile.
for example, my enum:
sealed trait ProcessingStatus extends EnumEntry with UpperSnakecase
object ProcessingStatus extends Enum[ProcessingStatus] with ReactiveMongoBsonEnum[ProcessingStatus] {
val values: IndexedSeq[ProcessingStatus] = findValues
case object Processing extends ProcessingStatus
case object Done extends ProcessingStatus
}
and I have play json serializer that explains how to serialize:
object JsonSerialization {
import reactivemongo.api.bson._
implicit object ProcessingStatusReader extends BSONReader[ProcessingStatus] {
override def readTry(bson: BSONValue): Try[ProcessingStatus] = bson match {
case BSONString(s) => bson.asTry[ProcessingStatus]
case _ => Failure(new RuntimeException("String value expected"))
}
}
implicit object ProcessingStatusWriter extends BSONWriter[ProcessingStatus] {
override def writeTry(t: ProcessingStatus): Try[BSONString] = Try(BSONString(t.entryName))
}
//Report Serializers
implicit val ProcessingStatusFormat: Format[ProcessingStatus] = EnumFormats.formats(ProcessingStatus)
implicit val ReportFormat: OFormat[Report] = Json.format[Report]
}
and now in my dao this does not compile:
import reactivemongo.play.json.compat.json2bson.{toDocumentReader, toDocumentWriter}
import serializers.JsonSerialization._
def findReport(reportId: String) = {
val test = BSONDocument("123" -> ProcessingStatus.Processing) // dosent compile
}
screenshot:
compilation error:
overloaded method apply with alternatives:
(elms: Iterable[(String, reactivemongo.api.bson.BSONValue)])reactivemongo.api.bson.BSONDocument <and>
(elms: reactivemongo.api.bson.ElementProducer*)reactivemongo.api.bson.BSONDocument
cannot be applied to ((String, enums.ProcessingStatus.Done.type))
val test = BSONDocument("status" -> ProcessingStatus.Done)
An IDE error is not a compilation error (recommend to use sbt and its console to tests).
Your code (simplified as bellow), is compiling fine, whatever is telling the IDE (which is wrong).
import reactivemongo.api.bson._
import scala.util.Try
trait ProcessingStatus {
def entryName = "foo"
}
object JsonSerialization {
implicit object ProcessingStatusWriter extends BSONWriter[ProcessingStatus] {
override def writeTry(t: ProcessingStatus): Try[BSONString] = Try(BSONString(t.entryName))
}
}
import JsonSerialization._
BSON.write(new ProcessingStatus {})
Note.1: writeTry doesn't override anything, so the modifier is useless (and can lead to missunderstanding).
Note.2: Try(..) with a pure value such as BSONString(t.entryName) is over-engineered, rather use Success(..).
Note.3: Convenient factories are available such as val w = BSONWriter[T] { t => ... }.
Edit:
The typeclass BSONWriter (as most typeclass) is invariant, so having a BSONWriter[T] in the implicit scope doesn't allow to resolve a BSONWriter[U] forSome { U <: T }.
trait ProcessingStatus {
def entryName: String
}
object ProcessingStatus {
case object Done extends ProcessingStatus { val entryName = "done" }
}
object JsonSerialization {
implicit object ProcessingStatusWriter extends BSONWriter[ProcessingStatus] {
override def writeTry(t: ProcessingStatus): Try[BSONString] = Try(BSONString(t.entryName))
}
}
import JsonSerialization._
BSON.write(ProcessingStatus.Done
/*
<console>:32: error: could not find implicit value for parameter writer: reactivemongo.api.bson.BSONWriter[ProcessingStatus.Done.type]
BSON.write(ProcessingStatus.Done)
*/
// --- BUT ---
BSON.write(ProcessingStatus.Done: ProcessingStatus)
// Success(BSONString(done))
Also exposing Done (and other cases) as ProcessingStatus in the API is working.
import reactivemongo.api.bson._
import scala.util.Try
sealed trait ProcessingStatus {
def entryName: String
}
object ProcessingStatus {
val Done: ProcessingStatus = new ProcessingStatus { val entryName = "done" }
}
object JsonSerialization {
implicit object ProcessingStatusWriter extends BSONWriter[ProcessingStatus] {
override def writeTry(t: ProcessingStatus): Try[BSONString] = Try(BSONString(t.entryName))
}
}
import JsonSerialization._
BSON.write(ProcessingStatus.Done)

Scala: macro to create an instance from a class body

I am building a DSL in Scala, and for that, I need to store "instances" of a class (Parent in this case), except these "instances" must be re-created several times at runtime. So instead I am storing "constructor functions" - a lambda that makes the instance.
consider the following code - imagine that userVar can change at runtime and the updated value must be used when constructing the instances.
class Parent {
def func(param: Any): Unit = { ... }
}
class User {
def construct(constr: => Parent): ParentWrapper = { ... }
var userVar = 13
construct(new Parent {
func(1)
func(userVar)
}
construct(new Parent {
func(userVar)
}
}
A more natural way of expressing what I want would be this (using the above definitions):
class User {
var userVar = 13
object ObjectA extends Parent {
func(1)
func(userVar)
}
construct(ObjectA)
}
However, that seems impossible, given that ObjectA is created immediately, and doesn't have a "constructor".
I am thinking, with some creative use of macros, I could instead do this:
class User {
var userVar = 13
constructMacro {
func(1)
func(userVar}
}
}
and have the constructMacro convert the code to construct(new Parent {code block goes here}).
How would I do that?
Or is there a better way to avoid the awkward construct(new Parent{...}) call? My requirement is that somewhere in the User class a reference is stored that I can repeatedly call and get new instances of the Parent definition that reflect new values used in their construction -- and the construct call should ideally return a wrapper object for that reference.
Unfortunately macros will not help.
Macro annotations (which expand before type checking) can't annotate code blocks:
#constructMacro {
func(1)
func(userVar)
}
is illegal.
Def macros (which expand during type checking) have their arguments type checked before macros are expanded. So
constructMacro {
func(1)
func(userVar)
}
doesn't compile:
Error: not found: value func
func(1)
Error: not found: value func
func(userVar)
That's the reason why macro shapeless.test.illTyped accepts a string rather than code block:
illTyped("""
val x: Int = "a"
""")
rather than
illTyped {
val x: Int = "a"
}
So the closest you can implement is
constructMacro("""
func(1)
func(userVar)
""")
def constructMacro(block: String): ParentWrapper = macro constructMacroImpl
def constructMacroImpl(c: blackbox.Context)(block: c.Tree): c.Tree = {
import c.universe._
val q"${blockStr: String}" = block
val block1 = c.parse(blockStr)
q"""construct(new Parent {
..$block1
})"""
}
You can annotate a variable
#constructMacro val x = {
func(1)
func(userVar)
}
// becomes
// val x: ParentWrapper = construct(new Parent {
// func(1)
// func(userVar)
// })
#compileTimeOnly("enable macro paradise to expand macro annotations")
class constructMacro extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro constructMacroImpl.impl
}
object constructMacroImpl {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
annottees match {
case q"$mods val $tname: $tpt = { ..$stats }" :: Nil =>
q"$mods val $tname: ParentWrapper = construct(new Parent { ..$stats })"
case _ =>
c.abort(c.enclosingPosition, "Not a val")
}
}
}
If I understood correctly, you just need to change object to def in the ObjectA block:
class User {
var userVar = 13
def makeParent = new Parent {
func(1)
func(userVar)
}
construct(makeParent)
}
and it'll do what you want.

How can two different class extend same class return same type in Scala

I'd like to be able to do something like this:
Suppose we have two Scala packages A and B. In B, I have two classes, like this:
class Structure{
case class StructureA(x:String, y:String)
case class StructureB(x:Int, y:Int)
}
class OperationB extend Structure{
def optB(someData:String): Array[(StructureA,StructureB)] = {...}
}
and in A, I have one class like this:
import B.Structure
class OperationA extend Structure {
def optA(data:Array[(StructureA,StructureB)]): Array[(StructureA,StructureB)] = {...}
}
And below is my project entry:
import B.{Structure,OperationB }
import A.OperationA
object Main {
def main(args: Array[String]): Unit = {
val BInstance = new OperationB()
val BResult = BInstance.optB(someData)
val AInstance = new OperationA()
val AResult = AInstance.optA(BResult)
}
}
The problem is:
BResult is typeof Array[(StructureA,StructureB)] but it can't be compiled, the error message is
type mismatch, expected Array[(A.StructureA,A.StructureB)] actual Array[(B.StructureA,B.StructureB)]
Actually I add this code in it, and it can be compiled successfully, but I think that is not the best solution.
import B.{Structure,OperationB }
import A.OperationA
object Main {
def main(args: Array[String]): Unit = {
val BInstance = new OperationB()
val AInstance = new OperationA()
// here convert it into proper type.
val BResult = BInstance.optB(someData).map{
case (a,b) => (a.asInstanceOf[AInstance.StructureA],b.asInstanceOf[AInstance.StructureB])
}
val AResult = AInstance.optA(BResult)
}
}
It has been bothering me for a long time, anyone can help me ?
Your code makes each instance of Structure get its own StructureA and StructureB types. Since they don't access Structure, there's no point doing so. Trying to extend Structure to save on imports is just a bad idea.
Instead
package structure // or could be B.structure, or directly B
case class StructureA(x:String, y:String)
case class StructureB(x:Int, y:Int)
// in A
package A
import structure._
class OperationA {
def optA(data:Array[(StructureA,StructureB)]): Array[(StructureA,StructureB)] = {...}
}
// in B
package B
import structure._
class OperationB {
def optB(someData:String): Array[(StructureA,StructureB)] = {...}
}
Another option is
object Structure {
case class StructureA(x:String, y:String)
case class StructureB(x:Int, y:Int)
}

Implicit value not found in method to method call

I'm trying to add a helper method to a config library by using implicit classes and type classes. However, I am extremely new to Scala (1 week) and have been unable to find out why the following code issues a compile error (I provide the working solution in a comment in the code)
Simplification of the third party package:
package pkg
class Config {
def hasPath(path: String) = { false }
def getString(path: String) = { "str" }
def getInt(path: String) = { 7 }
def getDouble(path: String) = { 3.14d }
}
And my example file:
import pkg._
object Helpers {
trait Extractor[T] {
def extract(cfg: Config, path: String): T
}
object Extractor {
implicit object IntExtractor extends Extractor[Int] {
def extract(cfg: Config, path: String) = {
99
}
}
}
implicit class BetterConfig(cfg: Config) {
def extract[T](path: String)(implicit extractor: Extractor[T]): T = {
extractor.extract(cfg, path)
}
// This example works if I add the implicit parameter:
// (implicit extractor: Extractor[T])
def extract[T](path: String, default: T): T = {
if ( cfg.hasPath(path) ) {
extract[T](path)
// ^ error here
} else {
default
}
}
}
}
object Demo extends App {
import Helpers._
val cfg = new Config
val x = cfg.extract("foo", 3)
println(s"x: ${x}")
}
This code gives the error could not find implicit value for parameter extractor: Helpers.Extractor[T]
Why can't the implicit value be found when calling extract(path) from within extract(path, default)? My understanding of the scoping rules or resolving the implicit, is wrong. I would have thought that when the call to extract(path) was made from within extract(path, default), the implicit would still be resolved from the companion object of Extractor.
I have tried this with Scala 2.10.6 and 2.11.8.
Your call needs an implicit Extractor[T], where nothing is known about T. It would be resolved from the companion object, if there was one, but there is no such method there.
Imagine it worked. Then
val cfg = new Config
val x = cfg.extract[String]("foo", "")
should also compile. But how would it work without an implicit Extractor[String] anywhere?

Implicit parameter resolution from surrounding scope

I'm not a fan of bringing implicit parameters into my code so where I use them I want to encapsulate their use. So I am trying to define an object that both wraps up calls to spray-json with exception handling and contains default implicit JsonFormats for each of my model classes. However the implicit parameters are not resolved unless they are imported into the client, calling code, which is exactly where I don't want them to be. Here's what I have so far (which doesn't resolve the implicit formatters), is there a way I can get what I want to work?
package com.rsslldnphy.json
import com.rsslldnphy.models._
import spray.json._
object Json extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
def parse[T](s:String)(implicit reader: JsonReader[T]): Option[T] = {
try { Some(JsonParser(s).convertTo[T]) }
catch { case e: DeserializationException => None }
}
}
NB. a JsonFormat is a type of JsonReader
EDIT: Here's what I've written based on #paradigmatic's second suggestion (which I can't get to work, I still get Cannot find JsonReader or JsonFormat type class for T). Am I missing something?
object Protocols extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
}
object Json {
def parse[T](s:String): Option[T] = {
import Protocols._
try { Some(JsonParser(s).convertTo[T]) }
catch { case e: DeserializationException => None }
}
}
For the record, this is a code snippet that does work, but that I'm trying to avoid as it requires too much of the client code (ie. it needs to have the implicits in scope):
object Json extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
}
object ClientCode {
import Json._
def person(s: String): Person = JsonParser(s).convertTo[Person]
}
You could declare the implicits in the companion objects:
object Person {
implicit val personFormat: JReader[Person] = jsonFormat1(Person)
}
object Animal {
implicit val animalFormat: JReader[Animal] = jsonFormat1(Animal)
}
The implicit resolution rules are very complex. You can find more information in this blog post. But if the compiler is looking for a typeclass T[A], it will look (soon or later) for it in the companion object of class/trait A.
EDIT: If the issue is only a problem of scope "pollution", you could just introduce some braces. With your code example, you could call the function parse as:
package com.rsslldnphy.json
import com.rsslldnphy.models._
import spray.json._
object Json extends DefaultJsonProtocol {
implicit val personFormat = jsonFormat1(Person)
implicit val animalFormat = jsonFormat1(Animal)
def parse[T](s:String)(implicit reader: JsonReader[T]): Option[T] = {
try { Some(JsonParser(s).convertTo[T]) }
catch { case e: DeserializationException => None }
}
}
object JsonFacade {
def optParse[T]( s: String ): Option[T] = {
import Json._
parse[T]( s )
}
}
Here the implicits "pollutes" only the optParse method.