I am trying to DRY up my code a little bit. I am using Circe to do some decoding. I have several classes and all of them have the form of:
import io.circe.derivation.deriveDecoder
import io.circe.derivation.renaming.snakeCase
import io.circe.parser.decode
import io.circe.{Decoder, Error}
// Getter[A] just defines some functions for getting the data from an endpoint.
class JSONGetter extends Getter[MyClass] {
implicit val decoder: Decoder[MyClass] = deriveDecoder[MyClass](io.circle.derivation.renaming.snakeCase)
// .. other parsing code here
}
I would like to stop repeating myself with the implicit so I set out to make a new trait:
trait JsonDecoding[A] {
implicit val decoder: Decoder[A] = deriveDecoder[A](io.circle.derivation.renaming.snakeCase)
}
So that I could shorten my class to:
class JSONGetter extends Getter[MyClass] with JsonDecoding[MyClass] {
// .. other parsing code here
}
This would be very convenient. However, I get A is not a class
when attempting to compile. I think that I cannot do this the way I want to here.
Is there a smart way to do this so I can not repeat myself when defining the implicit decoder that only changes in the class being decoded?
You can use automatic derivation
instead of semi-automatic derivation
or macro annotation @JsonCodec to simplify semi-automatic derivation
Let's assume that you prefer semi-automatic derivation rather than automatic one.
Extending a trait is an incorrect way
The thing is that
deriveDecoder
is a macro and it's important that the macro is expanded in a proper place. If you extend a trait and put implicit there then the macro is expanded in incorrect place.You can define your own macro annotation that will add necessary implicit
Scala | How can this code be put into a macro annotation?
How to reduce boilerplate code with Scala Macros in Scala 2?
Pass implicit parameter through multiple objects
Scala macro-based annotation reuse
Similarly for Cats type classes you can use Kittens to derive the type classes either atomatically
or semi-automatically
If you prefer semi-automatic derivation then you can use Katnip macro annotations rather than write necessary implicit
semiauto.functor
for every class