คุณสามารถทำซ้ำสมมติฐานทั้งหมดได้จนกว่าคุณจะพบข้อสันนิษฐานที่ตรงกัน:
Tactic Notation "summon" uconstr(ty) "as" ident(id) :=
match goal with H : _ |- _ => pose (id := H : ty) end.
เคล็ดลับคือคุณใช้ประเภทที่จะพบว่าไม่ใช่รูปแบบ แต่เป็นประเภท :) โดยเฉพาะอย่างยิ่ง หากคุณออกบางอย่างเช่น summon (P _) as id
Coq จะใช้ _
เป็นตัวแปรที่มีอยู่ที่ยังไม่ได้แก้ไข ในทางกลับกัน แต่ละสมมติฐานจะถูกพิมพ์เทียบกับ P _
โดยพยายามสร้างอินสแตนซ์ของหลุมนั้นไปพร้อมกัน เมื่อทำสำเร็จ pose
จะตั้งชื่อเป็น id
การวนซ้ำเกิดขึ้นเนื่องจาก match goal
จะลองอีกครั้งด้วยการจับคู่ที่แตกต่างกัน จนกว่าจะมีสิ่งค้างอยู่หรือทุกอย่างล้มเหลว
คุณสามารถกำหนดแบบฟอร์มโดยไม่ต้อง as
ที่เพิ่งตั้งชื่อสิ่งที่พบ it
(ในขณะที่เตะสิ่งอื่นออกไป):
Tactic Notation "summon" uconstr(ty) :=
let new_it := fresh "it"
in try (rename it into new_it); summon ty as it.
Ta-da!
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
summon (_ \/ _).
destruct it.
assumption.
summon (_ = _).
rewrite it.
assumption.
Qed.
คุณยังสามารถรับไวยากรณ์ =>
ของคุณได้ ฉันคิดว่ามันมีประโยชน์ไม่มากนัก แต่...
(* assumption of type ty is summoned into id for the duration of tac
anything that used to be called id is saved and restored afterwards,
if possible. *)
Tactic Notation "summon" uconstr(ty) "as" ident(id) "=>" tactic(tac) :=
let saved_id := fresh id
in try (rename id into saved_id);
summon ty as id; tac;
try (rename saved_id into id).
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
summon (_ \/ _) as H => destruct H.
assumption.
summon (_ = _) as H => rewrite H.
assumption.
Qed.
คำตอบเก่า
(คุณอาจต้องการอ่านสิ่งนี้ เนื่องจากวิธีแก้ปัญหาข้างต้นแตกต่างจากวิธีนี้จริงๆ และมีคำอธิบายเพิ่มเติมที่นี่)
คุณสามารถเรียกสมมติฐานที่ตรงกับรูปแบบประเภทให้เป็นชื่อด้วย eassert (name : ty) by eassumption.
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
eassert (HH : _ \/ _) by eassumption.
destruct HH.
assumption.
eassert (HH : _ = _) by eassumption.
rewrite HH.
assumption.
Qed.
เหตุใดจึงมีการปรับปรุงนี้ เนื่องจากขณะนี้ _ \/ _
และ _ = _
เป็นประเภทเต็ม ไม่ใช่แค่รูปแบบเท่านั้น พวกมันมีเพียงตัวแปรที่มีอยู่ที่ยังไม่ได้แก้ไข ระหว่าง eassert
ถึง eassumption
ตัวแปรเหล่านี้จะได้รับการแก้ไขในเวลาเดียวกันกับที่ตั้งสมมติฐานที่ตรงกัน สัญกรณ์ชั้นเชิงสามารถใช้ได้กับประเภทต่างๆ (เช่น เงื่อนไข) อย่างแน่นอน น่าเศร้าที่กฎการแยกวิเคราะห์ดูเหมือนจะมีอุบัติเหตุเล็กน้อย โดยเฉพาะอย่างยิ่ง สัญกรณ์ชั้นเชิงจำเป็นต้องมีคำที่ไม่ได้พิมพ์ (ดังนั้นเราจึงไม่พยายามและล้มเหลวในการแก้ไขตัวแปรเร็วเกินไป) ดังนั้นเราจึงต้องการ uconstr
แต่ ไม่มี luconstr
ซึ่งหมายความว่าเราถูกบังคับให้เพิ่มวงเล็บที่ไม่เกี่ยวข้อง เพื่อหลีกเลี่ยงอาการคลั่งไคล้วงเล็บ ฉันได้ทำการปรับปรุงไวยากรณ์ของ grab
ของคุณใหม่ ฉันยังไม่แน่ใจด้วยซ้ำว่าไวยากรณ์ =>
ของคุณสมเหตุสมผลหรือไม่ เพราะเหตุใดจึงไม่ลองนำชื่อไปไว้ในขอบเขตที่ดี แทนที่จะใช้เฉพาะใน =>
อย่างที่คุณบอกเป็นนัย
Tactic Notation "summon" uconstr(ty) "as" ident(id) :=
eassert (id : ty) by eassumption.
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
summon (_ \/ _) as HH.
destruct HH.
assumption.
summon (_ = _) as HH.
rewrite HH.
assumption.
Qed.
คุณสามารถสร้าง summon
-sans-as
ตั้งชื่อสมมติฐานที่พบ it
ในขณะที่ทำการบูทสิ่งอื่นภายใต้ชื่อนั้น
Tactic Notation "summon" uconstr(ty) "as" ident(id) :=
eassert (id : ty) by eassumption.
Tactic Notation "summon" uconstr(ty) :=
let new_it := fresh "it"
in (try (rename it into new_it); summon ty as it).
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
(* This example is actually a bad demonstration of the name-forcing behavior
because destruct-ion, well, destroys.
Save the summoned proof under the name it, but destroy it from another,
then observe the way the second summon shoves the original it into it0. *)
summon (_ \/ _) as prf.
pose (it := prf).
destruct prf.
assumption.
summon (_ = _).
rewrite it.
assumption.
Qed.
ตามสำนวนแล้วมันก็เป็นเช่นนั้นจริงๆ
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
summon (_ \/ _).
destruct it.
assumption.
summon (_ = _).
rewrite it.
assumption.
Qed.
ฉันเชื่อว่าคุณสามารถสร้าง Tactic Notation
s เฉพาะทางจำนวนมากเพื่อแทนที่อาร์กิวเมนต์ ident
ใน destruct
, rewrite
ฯลฯ ด้วย uconstrs
ประเภทโฮลลี่เหล่านี้ได้ หากคุณต้องการจริงๆ อันที่จริง summon _ as _
เกือบจะเป็น rename _ into _
ที่คุณแก้ไขแล้ว
ข้อแม้อีกประการหนึ่ง: assert
ทึบแสง; คำจำกัดความที่สร้างโดย summon
ดูเหมือนสมมติฐานใหม่ที่ไม่เปิดเผยว่ามีค่าเท่ากับข้อใดข้อหนึ่งแบบเก่า ควรใช้บางอย่างเช่น refine (let it := _ in _)
หรือ pose
เพื่อแก้ไขสิ่งนี้ แต่ Ltac-fu ของฉันไม่แข็งแกร่งพอที่จะทำเช่นนี้ ดูเพิ่มเติม: ปัญหานี้สนับสนุน transparent assert
ตามตัวอักษร
(คำตอบใหม่แก้ไขข้อแม้นี้)
person
HTNW
schedule
06.05.2019