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.
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.