วิธีการกำหนดฟังก์ชั่น inductively สองข้อโต้แย้งใน 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.

ดังนั้นฉันสนใจที่จะโน้มน้าว Coq ของการเลิกจ้าง


1
คุณได้ลองผ่าน l และ r ด้วยกันเป็นผลิตภัณฑ์แทนที่จะใช้การแกงหรือไม่ ที่ควรช่วยมันไปด้วย
ต่อ Vognsen

1
บางคนคิดว่าคำถามนี้เกี่ยวกับการเขียนโปรแกรมและอยู่นอกขอบเขตของเว็บไซต์นี้ ในขณะที่ฉันไม่แน่ใจว่าฉันเห็นด้วยคุณอาจต้องการทราบเกี่ยวกับปัญหาที่อาจเกิดขึ้น หากใครมีสิ่งที่จะพูดเกี่ยวกับความเหมาะสมโปรดเขียนในการสนทนาเมตาที่ฉันเชื่อมโยงกับ
Tsuyoshi Ito

3
คำถามนี้เกี่ยวกับการระบุขอบเขตที่ลดลงแบบซ้ำซ้อนในโครงสร้างข้อมูลเพื่อให้แน่ใจว่าการดำเนินการpairนั้นได้รับการกำหนดไว้อย่างดี Coq เป็นเพียงยานพาหนะ
Dave Clarke

คำตอบ:


12

คำจำกัดความ fixpoint ของ Coq ต้องการให้การโทรแบบเหนี่ยวนำได้รับอาร์กิวเมนต์ที่มีโครงสร้างน้อยกว่า ลึกลงไปโครงสร้างของ fixpoint จะใช้อาร์กิวเมนต์ตัวเดียว: ไม่มีแนวคิดในตัวของคำนิยามแบบเรียกซ้ำสำหรับอาร์กิวเมนต์สองตัว โชคดีที่คำจำกัดความของโครงสร้างที่เล็กลงของ Coq นั้นรวมถึงประเภทคำสั่งซื้อที่สูงกว่าซึ่งมีประสิทธิภาพมาก

นิยาม fixpoint สองอาร์กิวเมนต์ของคุณเป็นไปตามรูปแบบที่เรียบง่าย: อาร์กิวเมนต์แรกจะเล็กลงหรืออาร์กิวเมนต์แรกยังคงเหมือนเดิมและอาร์กิวเมนต์ที่สองจะเล็กลง รูปแบบทั่วไปนี้ค่อนข้างสามารถจัดการได้โดยการแก้ไขในง่าย

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.

สำหรับกรณีที่ซับซ้อนมากขึ้นหรือถ้ารสนิยมของคุณเรียกใช้วิธีการที่คุณสามารถใช้ recursion ใกล้ชิดกับวิธีที่จะสอนในหลักสูตรคณิตศาสตร์, การสร้าง fixpoint จากการคำนวณขั้นตอนและแยกอาร์กิวเมนต์ดี foundednessมักจะใช้มาตรการจำนวนเต็ม นอกจากนี้คุณยังสามารถทำให้ดูความหมายของคุณมากขึ้นเช่นโปรแกรมคลาสสิกในภาษาที่ไม่ใช่ทั้งหมดที่มีการเลิกจ้างที่แยกจากกันโดยใช้ภาษาพื้นเมืองProgram


ตอนนี้ฉันรู้ว่านี่คือสิ่งที่ฉันขอ!
yhirai

มันจะสร้างความแตกต่างหรือไม่ถ้าฉันผลักfix pair1 rเข้าไปในสาขาที่สองของระดับบนสุดmatch(และแน่นอนปรับสาขาแรกเพื่อกลับประเภทฟังก์ชันตาม)
วันที่

@plmday: ทั้งสองวิธีทำงาน พวกมันเทียบเท่ากับการขยายความหมายที่สมเหตุสมผลและที่สำคัญพวกเขาทั้งคู่พิมพ์ได้ดี (การเขียนซ้ำในมิติไม่ได้เปลี่ยนคุณสมบัติความแปรปรวนร่วมที่เกี่ยวข้อง (positivity) ใด ๆ ที่เกี่ยวข้อง)
Gilles 'หยุดชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.