2015-11-06 70 views
1

此問題與this one緊密相關,但不完全相同:它是相同的上下文,但是相反的問題。推導具有單個字段的案例類別的解碼器實例

我試圖得到一個CellDecoder[A],這基本上是一個String => A,爲A S中的情況下,班級,一個字段的類型都有一個CellDecoder

爲了做到這一點,我必須要求:

  • A是變形到R,其中RH :: HNil一個亞型。
  • HCellDecoder實例。

即:

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

我遇到的問題是,一旦我通過相關CellDecoder實例翻了StringH,我有點卡住:ev允許我把一個R變成H :: HNil,但不是H :: HNil變成R。沒有R,我無法使用我的Generic.Aux[A, R]來獲得最終的A實例。

事實證明,將我的H :: HNil轉換爲R的作品,但我不知道爲什麼,也不能說服自己,永遠是這種情況。

我認爲要求R嚴格等於H :: HNil(也就是說,要有R =:= HNil),但是然後隱含不能解決。

有沒有辦法做我想做的事情?

回答

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