使用单个字段派生案例类的解码器实例 [英] Deriving decoder instances of case classes with a single field
问题描述
这个问题与这个密切相关一个,但不完全相同:上下文相同但问题相反.
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 A
s that are case classes with a single field whose type has a CellDecoder
.
为了做到这一点,我需要:
In order to do this, I need to require:
A
可转换为R
,其中R
是H :: HNil
的子类型.H
拥有CellDecoder
实例.
A
to be transformable toR
, whereR
is a subtype ofH :: HNil
.H
to haveCellDecoder
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]
来获得最终的
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屋!