【问题标题】:Decoding Shapeless Tagged Types解码无形标记类型
【发布时间】:2018-06-18 20:52:03
【问题描述】:

鉴于以下关于菊石的情况:

@ 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

当明确拼写出String @@ Foo时有效:

@ val x: String @@ Foo = tag[Foo][String]("foo") 
x: String @@ Foo = "foo"

@ implicitly[Decoder[String @@ Foo]] 
res10: Decoder[String @@ Foo] = io.circe.Decoder$$anon$21@2b17bb37

但是,在定义类型别名时:

@ type FooTypeAlias = String @@ Foo 
defined type FooTypeAlias

它没有编译:

@ implicitly[Decoder[FooTypeAlias]] 
cmd12.sc:1: diverging implicit expansion for type io.circe.Decoder[ammonite.$sess.cmd11.FooTypeAlias]
starting with method decodeTraversable in object Decoder
val res12 = implicitly[Decoder[FooTypeAlias]]
                      ^
Compilation Failed

这是为什么呢?有没有已知的“修复”?

【问题讨论】:

标签: scala shapeless circe


【解决方案1】:

你很幸运,在同一天遇到了两个编译器错误。这个是scala/bug#8740。好的?新闻是this comment 中有一个部分修复等待有人站出来进行 PR(也许这就是你)。我相信它是部分的,因为它看起来适用于特定标签,但不适用于通用标签(我不是 100% 确定)。

你看到一个发散的隐式扩展的原因真的很有趣。编译器可以在一个步骤中展开所有别名(基本上从FooTypeAlias |= String with Tagged[Foo] 开始)或不展开任何东西。因此,当它比较 String @@ FooA @@ B 时,它不会扩展,因为它们按原样匹配。但是当它比较FooTypeAliasA @@ B 时,它会完全扩展,最终会出现必须比较精炼类型的情况,其中一个包含类型变量(请参阅我的answer 到您的其他相关问题)。在这里,我们精心设计的抽象再次崩溃,约束的顺序开始变得重要。你作为程序员,看着A with Tagged[B] <:< String with Tagged[Foo] 知道最好的匹配是A =:= StringB =:= Foo。然而 Scala 将首先比较 A <:< StringA <:< Tagged[Foo] 并得出结论 A <:< Tagged[Foo] with String(是的,相反)留下 NothingB。但是等等,我们需要一个隐含的Decoder[A]! - 循环发送给我们。所以A 过度约束而B 约束不足。

编辑:如果我们将@@ 抽象化以防止编译器去锯齿:milessabin/shapeless#807,它似乎可以工作。但现在它装箱了,我无法让数组工作。

【讨论】:

    猜你喜欢
    • 2018-06-18
    • 2017-08-21
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2018-06-01
    相关资源
    最近更新 更多