Рассмотрим процесс расширения Meta[Message1]
:
- При расширении
Meta[Message1]
с помощью message
компилятору необходимо Meta[Field3 :: Group1 :: HNil]
- Позже, при расширении
Meta[Group1]
с помощьюgroup
ему нужно Meta[Field1 :: Field2 :: HNil]
Компилятор видит, что в этой ветке он уже имеет расширенный конструктор типов ::
, по крайней мере, такой же сложности (т. Е. С таким же количеством элементов вHList
).Таким образом, предполагается, что эта ветвь расширения приводит к бесконечному циклу и сообщает о неявной дивергенции.
Чтобы предотвратить такое поведение, вы можете использовать shapeless.Lazy
.Из документации:
Оборачивает лениво вычисленное значение.Также обходит циклы во время неявного поиска или неправильные неявные расхождения, как показано ниже, и лениво удерживает соответствующее неявное значение.
Так что, чтобы исправить эту проблему, вы можете заключить в Lazy
расширение Head
в hcons
:
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
к другому).