使用单个字段派生案例类的解码器实例

时间:2015-11-06 21:35:15

标签: scala shapeless

这个问题与this one密切相关,但不完全相同:它是相同的背景,但却是相反的问题。

我试图为CellDecoder[A]派生一个String => A,其本质上是A,它是一个案例类,其中一个字段的类型为{{1} }}

为了做到这一点,我需要:

  • CellDecoder可转换为A,其中RR的子类型。
  • H :: HNil拥有H个实例。

那是:

CellDecoder

我遇到的问题是,一旦我通过相关implicit def caseClassCellDecoder[A, R, H](implicit gen: Generic.Aux[A, R], ev: R <:< (H :: HNil), d: CellDecoder[H] ): CellDecoder[A] = ??? 个实例将String变为H,我就会受到欢迎卡住:CellDecoder允许我将ev转换为R,而不是H :: HNil转换为H :: HNil。没有R,我无法使用R获取最终Generic.Aux[A, R]个实例。

事实证明,将我的A投放到H :: HNil作品中,但我不确定原因,并且无法说服自己,事情总是如此

我考虑过要求R严格等于R(也就是说,要H :: HNil),但这意味着无法解决。

有没有办法做我想做的事情?

1 个答案:

答案 0 :(得分:2)

我确实使用了=:=而不是<:<但是交换了RH::HNil的边,这似乎有效:

case class CellDecoder[A](decode: String => A)

implicit val stringCellDecoder: CellDecoder[String] = CellDecoder(identity)

implicit def caseClassCellDecoder[A, R, H](implicit
                                           gen: Generic.Aux[A, R],
                                           ev: (H :: HNil) =:= R,
                                           d: CellDecoder[H]
                                            ): CellDecoder[A] = CellDecoder(
  (str: String) => gen.from(ev(d.decode(str)::HNil))
)

所以我能够按如下方式使用它:

case class TestDecoder(test: String)

def doDecode[A: CellDecoder](str: String): A = {
  implicitly[CellDecoder[A]].decode(str)
}

doDecode[TestDecoder]("encoded value")