Як визначити функцію індуктивно на двох аргументах у Coq?


14

Як я можу переконати Coq, що рекурсивна функція, наведена нижче, припиняється? Функція бере два індуктивних аргументи. Інтуїтивно рекурсія припиняється, оскільки будь-який аргумент розкладається.

Зокрема, функція приймає два дерева як вхідні дані.

Inductive Tree :=
| Tip: Tree
| Bin: Tree -> Tree -> Tree.

На Деревах мені подобається робити наступний стиль індукції.

Inductive TreePair :=
| TipTip : TreePair
| TipBin : Tree -> Tree -> TreePair
| BinTip : Tree -> Tree -> TreePair
| BinBin : TreePair -> TreePair -> TreePair.

Fixpoint pair (l r: Tree): TreePair :=
  match l with
    | Tip =>
      match r with
        | Tip => TipTip
        | Bin rl rr => TipBin rl rr
      end
    | Bin ll lr =>
      match r with
        | Tip => BinTip ll lr
        | Bin rl rr => BinBin (pair l rl) (pair lr r)
      end
  end.

Визначення TreePair прийнято, але визначення пари функцій видає повідомлення про помилку:

Error: Cannot guess decreasing argument of fix.

Тож мені цікаво, як переконати Кока в припиненні.


1
Ви пробували пропускати l і r разом як продукт, а не використовувати каррі? Це повинно допомогти цьому.
Per Vognsen

1
Деякі люди думають, що це питання стосується програмування та поза межами цього веб-сайту. Хоча я не впевнений, чи згоден я, ви можете дізнатися про потенційну проблему. Якщо у когось є що сказати про доцільність, будь ласка, напишіть на мета-дискусії, до якої я посилався.
Цуйосі Іто

3
Це питання стосується конкретизації монотонно зменшуваних меж для структур даних з метою забезпечення pairчітко визначеної операції . Coq - просто транспортний засіб.
Дейв Кларк

Відповіді:


12

Визначення точки корекції Coq вимагає, щоб індуктивні виклики отримували структурно менший аргумент. У глибині думки конструкція фіксованої точки бере один аргумент: немає вбудованої концепції рекурсивного визначення двох аргументів. На щастя, визначення Coq як структурно менший включає типи вищого порядку, які надзвичайно потужні.

Ваше визначення двоаргументової точки фіксування відповідає простому шаблону: або перший аргумент стає меншим, або перший аргумент залишається ідентичним, а другий аргумент стає меншим. Цей досить розповсюджений зразок можна вирішити за допомогою простого виправлення.

Fixpoint pair l := fix pair1 (r : Tree) :=
  match l with
    | Tip => match r with
              | Tip => TipTip
              | Bin rl rr => TipBin rl rr
            end
    | Bin ll lr => match r with
                    | Tip => BinTip ll lr
                    | Bin rl rr => BinBin (pair1 rl) (pair lr r)
                   end
  end.

Для більш складних випадків, або якщо ваші смаки виконуються таким чином, ви можете використовувати рекурсію ближче до того, як її викладають на курсах з математики, будуючи точку фіксації з крокового обчислення та окремого аргументованого аргументу , часто використовуючи цілий показник . Ви також можете зробити своє визначення більш схожим на класичну програму на неповній мові з окремим закінченням, використовуючи Programпросторіччя .


Тепер я знаю, що це я просив!
yhirai

чи зміниться це, якщо я натисну fix pair1 rна другу гілку верхнього рівня match(і, звичайно, адаптую першу гілку, щоб відповідно повернути тип функції)?
день

@plmday: робота в обох напрямках. Вони еквівалентно екстенсіональні для певного розумного визначення розширення, і що ще важливіше, вони обидва добре набрані (розширення перезапису не змінює жодного з відповідних властивостей коваріації (позитивності)).
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.