考虑下面定义的功能。它的作用并不重要。
Require Import Ring.
Require Import Vector.
Require Import ArithRing.
Fixpoint
ScatHUnion_0 {A} (n:nat) (pad:nat) : t A n -> t (option A) ((S pad) * n).
refine (
match n return (t A n) -> (t (option A) ((S pad)*n)) with
| 0 => fun _ => (fun H => _)(@nil (option A))
| S p =>
fun a =>
let foo := (@ScatHUnion_0 A p pad (tl a)) in
(fun H => _) (cons _ (Some (hd a)) _ (append (const None pad) foo))
end
).
rewrite <-(mult_n_O (S pad)); auto.
replace (S pad * S p) with ( (S (pad + S pad * p)) ); auto; ring.
Defined.
我想证明
Lemma test0: @ScatHUnion_0 nat 0 0 ( @nil nat) = ( @nil (option nat)).
完成后
simpl. unfold eq_rect_r. unfold eq_rect.
目标是
match mult_n_O 1 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = nil (option nat)
尝试用
完成时 apply trans_eq with (Vector.const (@None nat) (1 * 0)); auto.
destruct (mult_n_O 1); auto.
destruct
不起作用(请参阅下面的错误消息)。但是,如果我首先在引理中证明了完全相同的目标,或者甚至在证明中使用assert
,我可以应用并解决它,如下所示:
Lemma test1: @ScatHUnion_0 nat 0 0 ( @nil nat) = ( @nil (option nat)).
simpl. unfold eq_rect_r. unfold eq_rect.
assert (
match mult_n_O 1 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = nil (option nat)
) as H.
{
apply trans_eq with (Vector.const (@None nat) (1 * 0)); auto.
destruct (mult_n_O 1); auto.
}
apply H.
Qed.
有人可以解释为什么会这样,以及在遇到这种情况时应该如何考虑这种情况?
在Coq 8.4中我收到错误
Toplevel input, characters 0-21:
Error: Abstracting over the terms "n" and "e" leads to a term
"fun (n : nat) (e : 0 = n) =>
match e in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = const None n" which is ill-typed.
在Coq 8.5中我得到了错误
Error: Abstracting over the terms "n" and "e" leads to a term
fun (n0 : nat) (e0 : 0 = n0) =>
match e0 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = const None n0
which is ill-typed.
Reason is: Illegal application:
The term "@eq" of type "forall A : Type, A -> A -> Prop"
cannot be applied to the terms
"t (option nat) 0" : "Set"
"match e0 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end" : "t (option nat) n0"
"const None n0" : "t (option nat) n0"
The 2nd term has type "t (option nat) n0" which should be coercible to
"t (option nat) 0".
答案 0 :(得分:2)
@Vinz回答解释了原因,并建议Set Printing All.
显示了区别。问题是simpl.
简化了match
的返回类型。使用unfold ScatHUnion_0.
代替simpl.
,我可以直接在目标上使用destruct。
从根本上说,我的麻烦源于我想要说服类型系统0=0
与0=1*0
相同。 (顺便说一句,我仍然不知道最好的方法。)我使用mult_n_O
来表示,但它是不透明的,所以类型系统在检查时不能展开它这两种类型是平等的。
当我用我自己的Fixpoint
变体(不是不透明的)替换它时,
Fixpoint mult_n_O n: 0 = n*0 :=
match n as n0 return (0 = n0 * 0) with
| 0 => eq_refl
| S n' => mult_n_O n'
end.
并在ScatHUnion_0
的定义中使用它,引理很容易证明:
Lemma test0: @ScatHUnion_0 nat 0 0 ( @nil nat) = ( @nil (option nat)).
reflexivity.
Qed.
补充评论:
这是一个适用于原始不透明mult_n_O
定义的证明。它基于proof by Jason Gross。
它使用mult_n_O 1
将0=0
的类型设为generalize
。它使用set
来修改术语的隐式部分,例如eq_refl
中的类型,该类型仅在Set Printing All.
命令后可见。 change
也可以这样做,但replace
和rewrite
似乎无法做到这一点。
Lemma test02:
match mult_n_O 1 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = nil (option nat).
Proof.
Set Printing All.
generalize (mult_n_O 1 : 0=0).
simpl.
set (z:=0) at 2 3.
change (nil (option nat)) with (const (@None nat) z) at 2.
destruct e.
reflexivity.
Qed.
更新:感谢coq-club的人们,这是一个更简单的证据。
Lemma test03:
match mult_n_O 1 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = nil (option nat).
Proof.
replace (mult_n_O 1) with (@eq_refl nat 0);
auto using Peano_dec.UIP_nat.
Qed.
答案 1 :(得分:1)
我会说这是因为依赖类型,并且在两种情况下你都没有真正证明完全相同的东西(尝试Set Printing All.
来看隐式类型和隐藏信息)。
这种破坏失败的事实通常是因为依赖会引入一个不合适的术语,你必须更精确地指出你想破坏的东西(这里不是秘密,它是一个案例基础)。通过提取子引理,您可能已经删除了麻烦的依赖关系,现在破坏可以运行。