Ich arbeite an einer CSV-Parsing-Bibliothek (tabulate). Es verwendet einfache Typklassen für die Kodierung/Dekodierung: Die Kodierung erfolgt zum Beispiel mit Instanzen von CellEncoder
(um eine einzelne Zelle zu kodieren) und RowEncoder
(um ganze Zeilen zu kodieren).Ableiten von Klasseninstanzen für Fallklassen mit genau einem Feld
Mit formlos, ich habe es ziemlich einfach zu finden, um automatisch die folgenden Typklasseninstanzen ableiten:
RowEncoder[A]
wennA
ein Fall der Klasse, deren Felder alle haben eineCellEncoder
.RowEncoder[A]
wennA
ein ADT ist, dessen Alternativen alle eineRowEncoder
haben.CellEncoder[A]
WennA
ein ADT ist, dessen Alternativen alleCellEncoder
haben.
Die Sache ist, dreht sie die letzten fast völlig nutzlos in realen Situationen erwiesen: ein Alternative Fallklasse fast immer ADT ist, und ich kann nicht ein CellEncoder
für eine Fall-Klasse abgeleitet werden, die mehr als ein Feld hat .
Was ich jedoch gerne tun könnte, ist die Ableitung einer CellEncoder
für Fallklassen, die ein einzelnes Feld haben, dessen Typ eine CellEncoder
hat. Das würde deckt zum Beispiel Either
, scalaz des \/
, Katzen Xor
...
Dies ist, was ich bisher:
implicit def caseClass1CellEncoder[A, H](implicit gen: Generic.Aux[A, H :: HNil], c: CellEncoder[H]): CellEncoder[A] =
CellEncoder((a: A) => gen.to(a) match {
case h :: t => c.encode(h)
})
Dies funktioniert gut, wenn explizit verwendet:
case class Bar(xs: String)
caseClass1CellEncoder[Bar, String]
res0: tabulate.CellEncoder[Bar] = [email protected]
Ich kann es jedoch nicht implizit zum Funktionieren bringen, das folgende schlägt fehl:
implicitly[CellEncoder[Bar]]
>> could not find implicit value for parameter e: tabulate.CellEncoder[Test.this.Bar]
Ich habe auch versucht die folgenden, ohne mehr Erfolg:
implicit def testEncoder[A, H, R <: H :: HNil](implicit gen: Generic.Aux[A, R], c: CellEncoder[H]): CellEncoder[A] =
CellEncoder((a: A) => gen.to(a) match {
case h :: t => c.encode(h)
})
ich etwas fehle? Ist das, was ich versuche, überhaupt möglich?
Ich muss lange darüber nachdenken, aber ich kann bestätigen, dass es funktioniert. Zufälligerweise habe ich viel Zeit in Circes Code verbracht, um die automatische Typklassenableitung von Fallklassen zu verstehen, also danke sowohl für diese Antwort als auch für Circe! –
Ich kämpfe mit dem Dualen dieses Problems - schreibe einen 'CellDecoder' (' String => A'), da das 'R <:
@NicolasRinaudo Eine neue Frage wäre angebracht. –