[英]Shapeless HList implicit resolution - diverging implicit expansion
这真是困扰我。 我收到diverging implicit expansion for type Meta[Field2 :: HNil]
错误的diverging implicit expansion for type Meta[Field2 :: HNil]
但我尝试编译以下内容:
case class Field() extends StaticAnnotation
case class Group() extends StaticAnnotation
case class Message() extends StaticAnnotation
@Field case class Field1(value: String)
@Field case class Field2(value: String)
@Field case class Field3(value: String)
@Group case class Group1(field1: Field1, field2: Field2)
@Message case class Message1(field3: Field3, group1: Group1)
trait Meta[T]
object Meta {
implicit val hNil: Meta[HNil] = new Meta[HNil] {}
implicit def field[TField](implicit a: Annotation[Field, TField]): Meta[TField] = new Meta[TField] {}
implicit def hcons[Head, Tail <: HList](implicit h: Meta[Head], t: Meta[Tail]) : Meta[H :: T] = new Meta[H :: T] {}
implicit def group[TGroup, ParamList <: HList](implicit a: Annotation[Group, TGroup], g: Generic.Aux[TGroup, ParamList], p: Meta[ParamList]): Meta[TGroup] = new Meta[TGroup] {}
implicit def message[TMessage, ParamList <: HList](implicit a: Annotation[Message, TMessage], g: Generic.Aux[TMessage, ParamList], p: Meta[ParamList]): Meta[TMessage] = new Meta[TMessage] {}
}
object TestApp extends App {
// throws compile exception here...
implicitly[Meta[Message1]]
}
考虑扩展Meta[Message1]
:
message
扩展Meta[Message1]
时,编译器需要Meta[Field3 :: Group1 :: HNil]
group
扩展Meta[Group1]
时,需要Meta[Field1 :: Field2 :: HNil]
编译器看到,在该分支中,它已经扩展了类型构造器::
,其复杂度至少相同(即, HList
的元素数相同)。 因此,它假定此扩展分支会导致无限循环,并报告隐式发散。
要防止此行为,可以使用shapeless.Lazy
。 从文档中:
包装延迟计算的值。 还可以避开隐式搜索过程中的循环,或错误的隐式发散度,如下所示,并懒惰地保存相应的隐式值。
因此,要解决此问题,您可以在hcons
Head
的扩展包装在Lazy
中:
implicit def hcons[Head, Tail <: HList](implicit
h: Lazy[Meta[Head]],
t: Meta[Tail]
): Meta[Head :: Tail] =
new Meta[Head :: Tail] {}
通常你应该在包装Lazy
的头扩展中HList
和Coproduct
规则,也扩大Repr
的Generic
规则。 我认为,后者在这里不是必需的,因为您将需要通过hcons
规则(已经具有Lazy
,以从一个Group
或Message
传递到另一个)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.