1

Imagine I have a Box that can hold animals of some type.
This Box can be given raw data which should be transformed/serialized into an animal of the same type of those already in the Box.
In other words, if a Box of dogs is given some "data", I want to validate that the "data" is another dog.

trait Animal
trait Dog extends Animal
trait Cat extends Animal   

 class Box[T<:Animal](elems: List[T]) {

      def receiveNewAnimal(data: String): T = validate[T](data)(<implicit val>)
    }

Normally, when I want to validate "rawData" against a particular Animal, I would just do (example for dogs):

val getMyDog(data: String): Dog = validate[Dog](data)

However, I do not know which type of Animal a Box[T] holds.
If I let it be as is:

def receiveNewAnimal(data: String): T = validate[T](data)(<implicit val>)

I get a compilation error saying that I do not have an implicit for type T (even tough I have all the implicits possible for the sub-traits of Animal).
It appears I am not being able to tell the compiler, that I want to validate the data against the type of Animal the current Box contains.

  1. Why does this happen?
  2. Can it be solved and how?
cmhteixeira
  • 877
  • 11
  • 22
  • 1
    What is validate? And you talk about implicits - I can't see any. – user unknown Apr 14 '18 at 20:31
  • @user-unknown This is a mock example of more elaborate problem that I have. validate is a function which validates and transforms "json serialized data" into other data types. It does so by means of an implicit. Each "other data type" must naturally have an implicit. Did this help? – cmhteixeira Apr 14 '18 at 20:49
  • 2
    No. I'm a practical oriented dev and have to try things out. So I write my own validate-function and hope it is equivalent to yours? Do you know [mcve]? Copy/pasting some code into the REPL is fast. Copy into the editor, searching for the right imports is time consuming. Do I have the needed json-lib at all? Without import statement I can hardly tell. Maybe you can make up an example with a mock class/mock functions, which don't depend on json? If the asking person provides all info, the 50 readers of the code save 10 minutes each. By providing an [mcve] you'll often find the solution. – user unknown Apr 14 '18 at 20:59

1 Answers1

1

You have to transport the implicit value from the call-site at which the Box constructor is invoked to the validate method.


Assuming that there is something like the following typeclass:

trait Validatable[T]

and that validate requires T to be Validatable:

def validate[T : Validatable](serializedData: String): T = ???

you can do this:

trait Animal
trait Dog extends Animal
trait Cat extends Animal   

class Box[T <: Animal : Validatable](elems: List[T]) {
  def receiveNewAnimal(data: String): T = validate[T](data)
}

Alternatively, if your validate is declared with a second parameter list, you can do the same with the Box:

def validate2[T](serializedData: String)(implicit v: Validatable[T]): T = ???

class Box2[T <: Animal](elems: List[T])(implicit v: Validatable[T]) {
  def receiveNewAnimal(data: String): T = validate[T](data)(v)
}

What Validatable actually is isn't that important in this case, could be some ClassTag, could be some macro-generated token that provides some deserialization strategy.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93