f_equal
策略对涉及归纳构造函数的等式证明无条件有用。 a :: s = a' :: s
将成为这样一个目标,缩减为a = a'
。
将它与任意函数一起使用是另一回事。 4 mod 2 = 2 mod 2
会减少到4 = 2
,这显然是荒谬的。
我想知道是否有办法在不丢失信息的情况下自动应用f_equal
(或类似的) ,例如归纳构造者。
答案 0 :(得分:2)
这是一种仅使用一点Ltac将f_equal
专门化为归纳构造函数的方法:
Ltac f_equal_ind :=
match goal with
| [ |- ?G ] =>
tryif
(tryif assert (~ G); [ injection |]
then fail else idtac)
then
fail "Not an inductive constructor"
else
f_equal
end.
Require Import List.
Import ListNotations.
Goal forall (a a' : nat) s, a :: s = a' :: s.
intros.
f_equal_ind.
Abort.
Require Import Arith.
Goal 4 mod 2 = 2 mod 2.
Fail f_equal_ind.
(* The command has indeed failed with message:
In nested Ltac calls to "f_equal_ind" and "f_equal_ind", last call failed.
Tactic failure: Not an inductive constructor. *)
我必须说结果特别复杂,如果有更简单的方法,我不会感到惊讶。我的想法是测试我们是否正在使用injection
进行原始相等,而tryif
期望一个否定的原始相等性。嵌套{{3}}是因为assert (~ G); [ injection |]
部分仅用于测试,但我们不想保留此创建的子目标。
答案 1 :(得分:2)
这是使用Ltac2的另一种非骇客方式(在Ltac2的作者Pierre-MariePédrot的帮助下):
From Ltac2 Require Import Ltac2.
Ltac2 is_constructor c := match Constr.Unsafe.kind c with
| Constr.Unsafe.Constructor _ _ => true
| _ => false
end.
Ltac2 not_a_constructor f :=
let msg :=
Message.concat (Message.of_constr f) (Message.of_string " is not a constructor")
in
Control.zero (Tactic_failure (Some msg)).
Ltac2 dest_app c := match Constr.Unsafe.kind c with
| Constr.Unsafe.App f args => (f, args)
| _ => (c, Ltac2.Array.make 0 constr:(Type))
end.
Ltac2 f_equal_ind () :=
lazy_match! goal with
| [ |- ?lhs = _ ] =>
let (f, _) := dest_app lhs in
match is_constructor f with
| true => f_equal
| false => Control.zero (not_a_constructor f)
end
| [ |- _ ] =>
Control.zero (Tactic_failure (Some (Message.of_string "Goal is not an equality")))
end.
Ltac2 Notation "f_equal_ind" := f_equal_ind ().
(* Tests *)
Require Import List.
Import ListNotations.
Require Import Arith.
Goal forall (a a' : nat) s, a :: s = a' :: s.
intros.
f_equal_ind. (* a = a' *)
Abort.
Goal True.
Fail f_equal_ind.
(*
The command has indeed failed with message:
Uncaught Ltac2 exception: Tactic_failure (Some (message:(Goal is not an equality)))
*)
Abort.
Goal 1 mod 2 = 3 mod 4.
Fail f_equal_ind.
(*
The command has indeed failed with message:
Uncaught Ltac2 exception: Tactic_failure (Some (message:(Nat.modulo is not a constructor)))
*)
Abort.
您可以在https://coq.github.io/doc/master/refman/proof-engine/ltac2.html上找到Ltac2文档。该版本将随Coq 8.11一起发布,但是可以在https://github.com/coq/ltac2/branches/all的各个分支中找到与Coq先前版本兼容的源。