Я работаю над библиотекой анализа CSV (tabulate). Он использует классы простого типа для кодирования/декодирования: например, кодирование выполняется с помощью экземпляров CellEncoder
(для кодирования одной ячейки) и RowEncoder
(для кодирования целых строк).Производящие экземпляры класса класса для классов классов с одним полем
Использование бесформенный, я нашел, что это довольно просто, чтобы автоматически получить следующие экземпляры класса типа:
RowEncoder[A]
еслиA
случай класс, все поля имеютCellEncoder
.RowEncoder[A]
, еслиA
является ADT, у всех альтернатив естьRowEncoder
.CellEncoder[A]
еслиA
является ADT, у всех альтернатив естьCellEncoder
.
Дело в том, этот последний оказывается почти полностью бесполезным в реальных жизненных ситуациях: альтернативы АТД являются почти всегда тематические классы, и я не могу вывести CellEncoder
для случая класса, который имеет более чем одно поле ,
Что бы я хотел сделать, однако, вывести CellEncoder
для классов классов, которые имеют одно поле, тип которого имеет CellEncoder
. Это будет включать, например, Either
, scalaz годов \/
, кошки Xor
...
Это то, что я до сих пор:
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)
})
Это прекрасно работает при использовании в явном виде:
case class Bar(xs: String)
caseClass1CellEncoder[Bar, String]
res0: tabulate.CellEncoder[Bar] = [email protected]
Я не могу заставить его работать неявно:
implicitly[CellEncoder[Bar]]
>> could not find implicit value for parameter e: tabulate.CellEncoder[Test.this.Bar]
Я также попытался следующие, не больше успеха:
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)
})
я упускаю что-то? Является ли то, что я пытаюсь сделать, даже возможно?
Мне нужно долго думать об этом, но я могу подтвердить, что он работает. Кстати, я много времени проводил в коде Цирце, чтобы понять автоматическое определение классов классов классов, так что спасибо за этот ответ и Circe! –
Я борюсь с дуальным из этой проблемы - написав «CellDecoder» ('String => A'), поскольку в этом контексте« R <:
@NicolasRinaudo Новый вопрос будет уместным. –