簡體   English   中英

無形HList隱式分辨率-發散的隱式擴展

[英]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的頭擴展中HListCoproduct規則,也擴大ReprGeneric規則。 我認為,后者在這里不是必需的,因為您將需要通過hcons規則(已經具有Lazy ,以從一個GroupMessage傳遞到另一個)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM