Pracuję nad biblioteką analizy parsowania CSV (tabulate). Wykorzystuje proste klasy typów do kodowania/dekodowania: kodowanie odbywa się na przykład w instancjach CellEncoder
(do kodowania pojedynczej komórki) i RowEncoder
(w celu zakodowania całych wierszy).Instancje klasy typu wyprowadzającego dla klas przypadków z dokładnie jednym polem
Korzystanie bezkształtne, Znalazłem to całkiem proste do automatycznego uzyskania następujących przypadkach klasy typ:
RowEncoder[A]
jeśliA
jest klasą sprawa, której pola wszyscy mająCellEncoder
.- Jeśli jest ADT, którego wersje alternatywne mają
RowEncoder
. CellEncoder[A]
Jeśli jest ADT, którego alternatywy wszystkie mająCellEncoder
.
Chodzi o to, ten ostatni okazuje się być prawie całkowicie bezużyteczne w rzeczywistych sytuacjach życiowych: alternatywy wykonania ADT są prawie zawsze klas sprawy, a ja nie mogę czerpać CellEncoder
dla klasy tak, że ma więcej niż jedno pole .
Co jednak chciałbym zrobić, to wypisz CellEncoder
dla klas przypadków, które mają pojedyncze pole, którego typ ma CellEncoder
. To by pokryć na przykład Either
, scalaz'S \/
, koty Xor
...
To, co mam tak daleko:
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)
})
Działa to dobrze, gdy stosowane wprost:
case class Bar(xs: String)
caseClass1CellEncoder[Bar, String]
res0: tabulate.CellEncoder[Bar] = [email protected]
Nie mogę jednak uruchomić go w sposób domyślny. Następuje błąd:
implicitly[CellEncoder[Bar]]
>> could not find implicit value for parameter e: tabulate.CellEncoder[Test.this.Bar]
Próbowałem zostały również następujące, bez dalszych sukcesów:
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)
})
jestem brakuje czegoś? Czy to, co próbuję zrobić, nawet możliwe?
Muszę długo i ciężko o tym myśleć, ale mogę potwierdzić, że to działa. Przypadkowo spędziłem dużo czasu w kodzie Circe'a, aby zrozumieć automatyczne wyprowadzanie klas klas przypadków, więc dziękuję za odpowiedź i Circe! –
Zmagam się z podwójnym problemem - pisanie 'CellDecoder' (' String => A'), ponieważ 'R <:
@NicolasRinaudo Nowe pytanie byłoby odpowiednie. –