posso facilmente genericamente derivare un codec per una famiglia di classe cassa sigillata simili:Derivando circe Codec per una famiglia caso classe chiusa dove basamento tratto ha un (sigillato) Tipo di utente
import io.circe._
import io.circe.generic.auto._
sealed trait Base
case class X(x: Int) extends Base
case class Y(y: Int) extends Base
object Test extends App {
val encoded = Encoder[Base].apply(Y(1))
val decoded = Decoder[Base].apply(encoded.hcursor)
println(decoded) // Right(Y(1))
}
Tuttavia, se aggiungo un membro di tipo alla classe di base che non posso più farlo, anche se è delimitata da un tratto sigillato:
import io.circe._
import io.circe.generic.auto._
sealed trait Inner
case class I1(i: Int) extends Inner
case class I2(s: String) extends Inner
sealed trait Base { type T <: Inner }
case class X[S <: Inner](x: S) extends Base { final type T = S }
case class Y[S <: Inner](y: S) extends Base { final type T = S }
object Test extends App {
val encodedInner = Encoder[Inner].apply(I1(1))
val decodedInner = Decoder[Inner].apply(encodedInner.hcursor) // Ok
println(decodedInner) // Right(I1(1))
// Doesn't work: could not find implicit for Encoder[Base] etc
// val encoded = Encoder[Base].apply(Y(I1(1)))
// val decoded = Decoder[Base].apply(encoded.hcursor)
// println(decoded)
}
c'è un modo per ottenere ciò che voglio? In caso contrario, cosa posso cambiare per ottenere qualcosa di simile?
E se provaste con il pattern aux? per esempio. 'type Aux [A <: Input] = Base {type T = A}' quindi estendere da 'Aux'? Inoltre, hai davvero bisogno che sia un membro del tipo? – pyrospade
In effetti, sembra che le vostre classi case possano semplicemente prendere un 'Inner' come argomento invece di un' S <: Inner'. – pyrospade
Ho aggiunto una risposta, ma da allora la ho rivista per aggiungere ulteriori dettagli e spiegazioni, oltre a una migliore implementazione. – pyrospade