Anda dapat mengulangi semua asumsi hingga Anda menemukan asumsi yang cocok:
Tactic Notation "summon" uconstr(ty) "as" ident(id) :=
match goal with H : _ |- _ => pose (id := H : ty) end.
Triknya adalah Anda mengambil tipe yang akan ditemukan bukan sebagai pola, tetapi, sebagai tipe :). Khususnya, jika Anda mengeluarkan sesuatu seperti summon (P _) as id
, maka Coq akan mengambil _
sebagai variabel eksistensial yang belum terpecahkan. Pada gilirannya, setiap asumsi akan diketik terhadap P _
, mencoba untuk membuat contoh lubang tersebut di sepanjang proses. Ketika seseorang berhasil, pose
menamainya id
. Iterasi muncul karena match goal
akan terus mencoba ulang dengan kecocokan yang berbeda hingga ada yang menempel atau semuanya gagal.
Anda dapat mendefinisikan formulir tanpa as
yang hanya memberi nama benda yang ditemukan it
(sambil membuang yang lainnya):
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.
Anda juga bisa mendapatkan sintaks =>
Anda. Menurutku itu tidak terlalu berguna, tapi...
(* 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.
Jawaban lama
(Anda mungkin ingin membaca ini, karena solusi di atas sebenarnya merupakan varian dari solusi ini, dan ada penjelasan lebih lanjut di sini.)
Anda dapat memanggil asumsi yang cocok dengan pola tipe ke dalam nama dengan 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.
Mengapa ini merupakan peningkatan? Karena _ \/ _
dan _ = _
sekarang bertipe full, bukan sekedar pola. Mereka hanya berisi variabel eksistensial yang belum terpecahkan. Antara eassert
dan eassumption
, variabel-variabel ini diselesaikan pada saat yang sama dengan asumsi pencocokan ditemukan. Notasi taktik pasti dapat bekerja dengan tipe (yaitu istilah). Sayangnya, tampaknya ada sedikit kesalahan dalam aturan parsing. Secara khusus, notasi taktik memerlukan istilah yang belum diketik (jadi kita tidak mencoba dan gagal menyelesaikan variabel terlalu dini), jadi kita memerlukan uconstr
, tetapi tidak ada luconstr
, artinya kami terpaksa menambahkan tanda kurung asing. Untuk menghindari bracket-mania, saya telah mengerjakan ulang sintaks grab
Anda. Saya juga tidak sepenuhnya yakin apakah sintaks =>
Anda masuk akal, karena mengapa tidak memasukkan nama tersebut ke dalam cakupan untuk selamanya, daripada hanya pada =>
, seperti yang Anda maksudkan?
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.
Anda dapat membuat summon
-sans-as
memberi nama asumsi yang ditemukan it
, sambil mem-boot apa pun dengan nama itu.
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.
Secara idiomatis, itu memang benar adanya
Lemma l0 : forall P1 P2, P1 \/ (P1 = P2) -> P2 -> P1.
Proof.
intros.
summon (_ \/ _).
destruct it.
assumption.
summon (_ = _).
rewrite it.
assumption.
Qed.
Saya yakin Anda dapat membuat sekumpulan Tactic Notation
khusus untuk menggantikan argumen ident
di destruct
, rewrite
, dll. dengan uconstrs
tipe berlubang ini, jika Anda benar-benar menginginkannya. Memang, summon _ as _
hampir merupakan rename _ into _
Anda yang dimodifikasi.
Peringatan lain: assert
buram; definisi yang dihasilkan oleh summon
tampak seperti asumsi baru yang tidak mengungkapkan bahwa definisi tersebut sama dengan salah satu asumsi lama. Sesuatu seperti refine (let it := _ in _)
atau pose
harus digunakan untuk memperbaiki ini, tapi Ltac-fu saya tidak cukup kuat untuk melakukan ini. Lihat juga: masalah ini menganjurkan transparent assert
secara literal.
(Jawaban baru memecahkan peringatan ini.)
person
HTNW
schedule
06.05.2019