解码具有标记类型的案例类

Kev*_*ith 6 scala shapeless circe

鉴于:

鉴于以下关于亚扪人:

@ import $ivy.`io.circe::circe-core:0.9.0` 

@ import $ivy.`io.circe::circe-generic:0.9.0`                   

@ import $ivy.`com.chuusai::shapeless:2.3.3` 

@ import shapeless.tag 
import shapeless.tag

@ trait Foo 
defined trait Foo

@ import io.circe._, io.circe.generic.semiauto._ 
import io.circe._, io.circe.generic.semiauto._

@ import shapeless.tag.@@ 
import shapeless.tag.@@

@ implicit def taggedTypeDecoder[A, B](implicit ev: Decoder[A]): Decoder[A @@ B] = 
    ev.map(tag[B][A](_)) 
defined function taggedTypeDecoder
Run Code Online (Sandbox Code Playgroud)

鉴于Foo:

@ case class F(x: String @@ Foo)  
defined class F
Run Code Online (Sandbox Code Playgroud)

我可以召唤一个Decoder[String @@ Foo]:

@ Decoder[String @@ Foo] 
res17: Decoder[String @@ Foo] = io.circe.Decoder$$anon$21@16b32e49
Run Code Online (Sandbox Code Playgroud)

但不是F:

@ deriveDecoder[F] 
cmd18.sc:1: could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[ammonite.$sess.cmd16.F]
val res18 = deriveDecoder[F]
                         ^
Compilation Failed
Run Code Online (Sandbox Code Playgroud)

我怎么能得到一个Decoder[F]

g.k*_*tev 8

这是一个无形的错误' Lazy- milessabin/shapeless#309

我有一个公关,让你的例子编译 - milessabin/shapeless#797(我检查过publishLocal)

基本上问题Lazy在于它过于急切地扩展类型别名(A @@ B是一个类型别名A with Tagged[B]),这反过来会触发Scala bug - scala/bug#10506

Scala bug看不到明确的解决方案.它是子类型与参数多态性问题的另一个化身,使类型推断变得复杂.它的要点是Scala执行子类型检查和类型推断在同一时间.但是,当我们把一些类型的变量,比如AB一个精致的类型一样A with Tagged[B](实际上瑟茜结束了寻找FieldType[K, A with Tagged[B]]地方FieldType是另一种类型的别名隐藏精致型),子类型,必须为每个组件单独检查.这意味着,我们在其中选择检查组件的顺序决定了的类型变量AB将受到限制.在某些情况下,它们会过度约束或约束不足,无法正确推断.

Apropo,无形测试显示了一种解决方法,但我不认为它适用于circe,因为它使用的是某种宏,而不是使用vanilla类型派生.

长话短说,你可以:

  1. 等待一个没有形状(请upvote #797)和随后的circe释放
  2. 不使用标记类型= /
  3. 尝试使用不同的编码而不使用精炼或结构类型 - 也许是alexknvl/newtypes?(我没试过)