Kev*_*ith 8 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.@@
Run Code Online (Sandbox Code Playgroud)
然后,我尝试定义通用标记类型解码器:
@ 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)
它在明确拼写时有效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
Run Code Online (Sandbox Code Playgroud)
但是,在定义类型别名时:
@ type FooTypeAlias = String @@ Foo
defined type FooTypeAlias
Run Code Online (Sandbox Code Playgroud)
它没有编译:
@ 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
Run Code Online (Sandbox Code Playgroud)
这是为什么?有没有已知的"修复?"
幸运的是,在同一天遇到两个编译器错误.这个是scala/bug#8740.好吗?新闻是在这个评论中有一个部分修复等待某人加强并制作PR(也许这就是你).我认为这是部分的,因为看起来它适用于特定的标签,但不适用于通用标签(我不是100%肯定).
你看到一个不同的隐式扩张的原因真的很有趣.编译器可以在一个步骤中扩展所有别名(基本上来自FooTypeAlias |= String with Tagged[Foo]
)或不扩展任何内容.因此,当它进行比较String @@ Foo
并且A @@ B
不会扩展时,因为它们会按原样匹配.但是,当它进行比较FooTypeAlias
和A @@ B
它完全扩张都与它的情况下有比较精致的类型,其中一个包含类型变量结束了(见我的回答给您的其他相关问题).在这里,我们精心设计的抽象再次破裂,约束的顺序开始变得重要.你作为程序员,看着A with Tagged[B] <:< String with Tagged[Foo]
知道最好的匹配是A =:= String
和B =:= Foo
.然而斯卡拉将先比较A <:< String
,并A <:< Tagged[Foo]
和它的结论是,A <:< Tagged[Foo] with String
(是的,在反向)留下Nothing
的B
.但是等等,我们需要隐含Decoder[A]
! - 它让我们循环.因此A
过度约束并B
受到限制.
编辑:如果我们制作@@
抽象以防止编译器脱离,似乎有效:milessabin/shapeless#807.但现在它是盒子,我无法使阵列工作.