scala – 解码无形标记类型
鉴于以下关于亚扪人:
@ 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/bug#8740.好吗?新闻是有一个部分修复在
this comment等待有人加强并制作PR(也许这就是你).我认为这是部分的,因为看起来它适用于特定的标签,但不适用于通用标签(我不是100%肯定).
你看到一个不同的隐式扩张的原因真的很有趣.编译器可以在一个步骤中扩展所有别名(主要来自FooTypeAlias | =带有Tagged [Foo]的String)或不扩展任何内容.因此,当它比较String @@ Foo和A @@ B时,它不会展开,因为它们按原样匹配.但是当它比较FooTypeAlias和A @@ B时,它会完全扩展,并且最终会在必须比较精炼类型的情况下,其中一个包含类型变量(请参阅我的answer到您的其他相关问题).在这里,我们精心设计的抽象再次崩溃,约束的顺序开始变得重要.你作为程序员,用标记[B]<:<查看A带有Tagged [Foo]的字符串知道最佳匹配是A =:= String和B =:= Foo.然而,Scala将首先比较A<:<字符串和A<:<标记[Foo]并得出结论A<:<使用String标记[Foo](是的,反之),为B留下Nothing但是等等,我们需要一个隐式解码器[A]! - 让我们循环播放.所以A过度约束而B受到限制. 编辑:如果我们制作@@ abstract以防止编译器进行deiasing:milessabin/shapeless#807似乎有效.但是现在它是盒子而我无法使数组工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |