【发布时间】:2015-11-06 09:09:47
【问题描述】:
我正在开发一个 CSV 解析库 (tabulate)。它使用简单的类型类进行编码/解码:例如,编码是通过CellEncoder(对单个单元格进行编码)和RowEncoder(对整行进行编码)的实例完成的。
使用 shapeless,我发现自动派生以下类型类实例非常简单:
-
RowEncoder[A]如果A是其字段都具有CellEncoder的案例类。 -
RowEncoder[A]如果A是一个ADT,其替代品都有RowEncoder。 -
CellEncoder[A]如果A是一个ADT,其替代品都有CellEncoder。
问题是,最后一个在现实生活中几乎完全没用:ADT 的替代方案几乎总是案例类,我无法为具有多个字段的案例类派生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] = tabulate.CellEncoder$$anon$2@7941904b
但是我不能让它隐式工作,以下失败:
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)
})
我错过了什么吗?我正在尝试做的事情是否可能?
【问题讨论】: