问题
This question is tightly related to this one, but not identical: it's the same context but the opposite problem.
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:
Ato be transformable toR, whereRis a subtype ofH :: HNil.Hto haveCellDecoderinstance.
That is:
implicit def caseClassCellDecoder[A, R, H](implicit
gen: Generic.Aux[A, R],
ev: R <:< (H :: HNil),
d: CellDecoder[H]
): CellDecoder[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.
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.
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?
回答1:
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")
来源:https://stackoverflow.com/questions/33576085/deriving-decoder-instances-of-case-classes-with-a-single-field