匹配 tactic/tactic 符号内的上下文模式
Match context pattern inside a tactic/tactic notation
我通过战术在我的目标中找到了规律。
为什么会失败:
Tactic Notation "my_context_match" uconstr(g) :=
match goal with
| |- context[g] => idtac
end.
my_context_match _.
虽然这成功了?
match goal with
| |- context[_] => idtac
end.
有什么方法可以写一个 my_context_match
,这样我就可以传递不完整的模式(上面有 _
)并查看我的目标中是否有任何内容与该模式匹配?
对 uconstr
的支持非常不完整。我刚刚报告了 #9321。请注意,即使这样也会失败:
Goal True.
let v := uconstr:(True) in
lazymatch constr:(v) with
| v => idtac
end. (* Error: No matching clauses for match. *)
正如@eponier 在评论中所建议的,您可以使用 open_constr
而不是 uconstr
。但是,这将留下未解决的 evar。这是一个行之有效的策略,不会留下未解决的 evars:
Tactic Notation "my_context_match" uconstr(g) :=
(* [match] does not support [uconstr], cf COQBUG(https://github.com/coq/coq/issues/9321),
so we use [open_constr] *)
let g := open_constr:(g) in
(* turning [g] into an [open_constr] creates new evars, so we must
eventually unify them with the goal *)
let G := match goal with |- ?G => G end in
(* We now search for [g] in the goal, and then replace the matching
subterm with the [open_constr] [g], so that we can unify the
result with the goal [G] to resolve the new evars we created *)
match G with
| context cG[g]
=> let G' := context cG[g] in
unify G G'
end.
Goal True /\ True.
my_context_match _.
my_context_match (_ /\ _).
Fail my_context_match (_ \/ _).
my_context_match True.
exact (conj I I).
Qed.
我通过战术在我的目标中找到了规律。
为什么会失败:
Tactic Notation "my_context_match" uconstr(g) :=
match goal with
| |- context[g] => idtac
end.
my_context_match _.
虽然这成功了?
match goal with
| |- context[_] => idtac
end.
有什么方法可以写一个 my_context_match
,这样我就可以传递不完整的模式(上面有 _
)并查看我的目标中是否有任何内容与该模式匹配?
对 uconstr
的支持非常不完整。我刚刚报告了 #9321。请注意,即使这样也会失败:
Goal True.
let v := uconstr:(True) in
lazymatch constr:(v) with
| v => idtac
end. (* Error: No matching clauses for match. *)
正如@eponier 在评论中所建议的,您可以使用 open_constr
而不是 uconstr
。但是,这将留下未解决的 evar。这是一个行之有效的策略,不会留下未解决的 evars:
Tactic Notation "my_context_match" uconstr(g) :=
(* [match] does not support [uconstr], cf COQBUG(https://github.com/coq/coq/issues/9321),
so we use [open_constr] *)
let g := open_constr:(g) in
(* turning [g] into an [open_constr] creates new evars, so we must
eventually unify them with the goal *)
let G := match goal with |- ?G => G end in
(* We now search for [g] in the goal, and then replace the matching
subterm with the [open_constr] [g], so that we can unify the
result with the goal [G] to resolve the new evars we created *)
match G with
| context cG[g]
=> let G' := context cG[g] in
unify G G'
end.
Goal True /\ True.
my_context_match _.
my_context_match (_ /\ _).
Fail my_context_match (_ \/ _).
my_context_match True.
exact (conj I I).
Qed.