Это один из случаев, когда поведение зависит от ... порядка устранения последствий.
Если вы измените сигнатуру на:
implicit def derive[A, L <: HList, H](
implicit gen: Generic.Aux[A, L],
isUnary: (H :: HNil) =:= L, // swapped
H: Lazy[Foo[H]] // with this
): Foo[A] = ...
, компилятор:
- попытайтесь найти
HList
L
, который мог бы быть в паре с A
- , затем докажите, что
L
равен некоторому H :: HNil
, вычисляющему H
в процессе - наконец, используя
H
для извлечения Lazy[Foo[H]]
, и вы успешно скомпилируете Foo[A].hello()
.
Когда эти два последних аргумента поменялись местами с тем, что у вас есть в вашем вопросе, компилятор должен
- принять некоторое
H
(что в нашем тестовом примере, скорее всего, НЕ БУДЕТ Int) - , затем принудительно попытайтесь настроить
L
для соответствия - , затем go обратно на
Generic
, который теперь вынужден доказать, что A
представимо некоторыми H :: HNil
где H
, скорее всего, не Int
и не в состоянии это сделать, но с ошибочной информацией об ошибке
Это один из этих случаев, который показывает, что бесформенный деривация на основе иногда бывает сложной, а также здесь показано, что бесформенные авторы предполагали в макросах, что наиболее вероятной причиной сбоя раскрытия макроса является то, что A
не относится к классу падежей, в то время как мы только что увидели, что это может быть также компилятор, приводящий к некоторым невозможным доказательствам, потому что логический вывод неверен, потому что мы решил их в неправильном порядке.