使用单个字段派生案例类的解码器实例 [英] Deriving decoder instances of case classes with a single field

查看:35
本文介绍了使用单个字段派生案例类的解码器实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与这个密切相关一个,但不完全相同:上下文相同但问题相反.

This question is tightly related to this one, but not identical: it's the same context but the opposite problem.

我正在尝试导出一个 CellDecoder[A],它本质上是一个 String =>A,对于 A 是具有单个字段的案例类,其类型具有 CellDecoder.

I'm trying to derive a CellDecoder[A], which is essentially a String => A, for As that are case classes with a single field whose type has a CellDecoder.

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

In order to do this, I need to require:

  • A 可转换为 R,其中 RH :: HNil 的子类型.
  • H 拥有 CellDecoder 实例.
  • A to be transformable to R, where R is a subtype of H :: HNil.
  • H to have CellDecoder instance.

即:

implicit def caseClassCellDecoder[A, R, H](implicit
  gen: Generic.Aux[A, R],
  ev: R <:< (H :: HNil),
  d: CellDecoder[H]
): CellDecoder[A] = ???

我遇到的问题是,一旦我通过相关的 CellDecoder 实例将 String 转换为 H,我我有点卡住了:ev 允许我将 R 变成 H :: HNil,但不是 H ::HNil 转换为 R.没有 R,我不能使用我的 Generic.Aux[A, R] 来获得最终的 A 实例.

The issue I'm having is that, once I've turned a String to an H through the relevant CellDecoder instance, I'm kind of stuck: ev allows me to turn an R into an H :: HNil, but not an H :: HNil into an R. Not having an R, I can't use my Generic.Aux[A, R] to get the final A instance.

事实证明,将我的 H :: HNil 转换为 R 是有效的,但我不确定为什么并且无法说服自己它总是就是这样.

It turns out that casting my H :: HNil into an R works, but I'm not sure why and can't convince myself that it'll always be the case.

我想过要求 R 严格等于 H :: HNil(也就是说,有一个 R =:= HNil),但随后隐式无法解析.

I thought about requiring R to be strictly equal to H :: HNil (that is, to have a R =:= HNil), but then the implicits fail to resolve.

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

Is there a way to do what I'm trying to do?

推荐答案

我确实使用了 =:= 而不是 <:< 但是交换了 =:=code>R 和 H::HNil 并且这似乎有效:

I did use =:= instead of <:< however swapped the sides of R and H::HNil and that seemed to work:

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))
)

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

So I was able to use it as follows:

case class TestDecoder(test: String)

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

doDecode[TestDecoder]("encoded value")

这篇关于使用单个字段派生案例类的解码器实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆