Functional programming Coq中带连词结论的前提分解
我经常需要做归纳加载来证明Coq中的目标,在Coq中,我通过归纳同时证明多个事情 问题是,我经常会得出以下形式的归纳假设:Functional programming Coq中带连词结论的前提分解,functional-programming,coq,dependent-type,coq-tactic,ltac,Functional Programming,Coq,Dependent Type,Coq Tactic,Ltac,我经常需要做归纳加载来证明Coq中的目标,在Coq中,我通过归纳同时证明多个事情 问题是,我经常会得出以下形式的归纳假设: forall a1 ... an, Premise1 -> Premise2 -> ... Premisek -> Conclusion1 /\ Conclusion2 /\ ... Conclusion_m 这很好,但是像eauto这样的战术真的不知道如何处理这样的事情,所以它在大多数情况下扼杀了自动化 我想知道的是,有没有一种方法可以自动
forall a1 ... an,
Premise1 -> Premise2 -> ... Premisek ->
Conclusion1 /\ Conclusion2 /\ ... Conclusion_m
这很好,但是像eauto这样的战术真的不知道如何处理这样的事情,所以它在大多数情况下扼杀了自动化
我想知道的是,有没有一种方法可以自动将这样一个前提分解成m个不同的前提,即
forall a1 ... an,
Premise1 -> Premise2 -> ... Premisek ->
Conclusion1
...
forall a1 ... an,
Premise1 -> Premise2 -> ... Premise_k ->
Conclusion_m
我遇到的主要问题是,我不知道如何匹配LTac中任意长度的箭头链。我可以硬编码到一定长度,但我希望有更好的方法
此外,如果有可能在Premise1中对所有析取组合进行双重分割。。前提是,这也会很有用。也许像这样的东西减去调试打印输出
Ltac foo :=
match goal with
| |- forall q, ?X =>
let x := fresh in intros x; idtac x q ; (try foo); generalize x as q; clear x
| |- ?X -> _ =>
let x := fresh in intros x; idtac x ; (try foo); generalize x; clear x
| |- _ /\ _ => repeat split
end; idtac "done".
Goal forall {T} (a1 a2 a3:T) P1 P2 P3 Q1 Q2 Q3, P1 a1 -> P2 a2 -> P3 a3 -> Q1 /\ Q2 /\ Q3.
foo.
这就给你留下了目标
3 subgoals (ID 253)
============================
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type) (Q1 : Prop),
Prop -> Prop -> P1 a1 -> P2 a2 -> P3 a3 -> Q1
subgoal 2 (ID 254) is:
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type),
Prop -> forall Q2 : Prop, Prop -> P1 a1 -> P2 a2 -> P3 a3 -> Q2
subgoal 3 (ID 255) is:
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type),
Prop -> Prop -> forall Q3 : Prop, P1 a1 -> P2 a2 -> P3 a3 -> Q3
也许是这样减去调试打印输出
Ltac foo :=
match goal with
| |- forall q, ?X =>
let x := fresh in intros x; idtac x q ; (try foo); generalize x as q; clear x
| |- ?X -> _ =>
let x := fresh in intros x; idtac x ; (try foo); generalize x; clear x
| |- _ /\ _ => repeat split
end; idtac "done".
Goal forall {T} (a1 a2 a3:T) P1 P2 P3 Q1 Q2 Q3, P1 a1 -> P2 a2 -> P3 a3 -> Q1 /\ Q2 /\ Q3.
foo.
这就给你留下了目标
3 subgoals (ID 253)
============================
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type) (Q1 : Prop),
Prop -> Prop -> P1 a1 -> P2 a2 -> P3 a3 -> Q1
subgoal 2 (ID 254) is:
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type),
Prop -> forall Q2 : Prop, Prop -> P1 a1 -> P2 a2 -> P3 a3 -> Q2
subgoal 3 (ID 255) is:
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type),
Prop -> Prop -> forall Q3 : Prop, P1 a1 -> P2 a2 -> P3 a3 -> Q3
我不是Ltac的专家,但我尝试了一下,想出了以下策略
Ltac decomp H :=
try match type of H with
context c [?A /\ ?B] =>
let H' := fresh H in
let Pa := context c[A] in
assert (H' : Pa) by (apply H);
let H'' := fresh H in
let Pb := context c[B] in
assert (H'' : Pb) by (apply H);
clear H;
rename H' into H;
rename H'' into H';
decomp H'
end.
Tactic Notation "decomp_hyp" hyp(H) := decomp H.
decomph搜索H中出现的连词,然后将其分解为H'和H,清除状态并递归调用自身
举一个简单的例子,这似乎是可行的。我不是Ltac的专家,但我尝试了一下,想出了以下策略
Ltac decomp H :=
try match type of H with
context c [?A /\ ?B] =>
let H' := fresh H in
let Pa := context c[A] in
assert (H' : Pa) by (apply H);
let H'' := fresh H in
let Pb := context c[B] in
assert (H'' : Pb) by (apply H);
clear H;
rename H' into H;
rename H'' into H';
decomp H'
end.
Tactic Notation "decomp_hyp" hyp(H) := decomp H.
decomph搜索H中出现的连词,然后将其分解为H'和H,清除状态并递归调用自身
举一个简单的例子,这似乎是可行的。谢谢,这很有帮助,但这并不是我想要的。我需要能够在调用归纳策略后进行拆分,这样我就可以得到Q1、Q2、Q3作为单独的归纳假设。谢谢,这很有帮助,但这不是我想要的。我需要能够在调用归纳策略后进行拆分,这样我就可以得到Q1、Q2、Q3作为单独的归纳假设。很好地了解了上下文和漏洞!如果目标类似于A/\B/\CI,那么它也应该递归地反编译H。我认为添加第二个递归调用decomp H就足够了。前提中的析取问题更难处理。了解上下文和漏洞很好!如果目标类似于A/\B/\CI,那么它也应该递归地反编译H。我认为添加第二个递归调用decomp H就足够了。房屋内的分隔问题更难处理。