[英]Why can I sometimes prove a goal via a lemma, but not directly?
考慮下面定義的函數。 它的作用並不重要。
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".
@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.
附加評論:
這是一個適用於原始opaque mult_n_O
定義的證明。 它基於Jason Gross的證明 。 它通過使用generalize
將mult_n_O 1
的類型操作為0=0
。 它使用set
來修改術語的隱式部分,例如eq_refl
的類型,該類型僅在Set Printing All.
之后可見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.
我會說這是因為依賴類型,並且在兩種情況下你都沒有真正證明完全相同的東西(嘗試Set Printing All.
查看隱式類型和隱藏信息)。
這種破壞失敗的事實通常是由於依賴會引入一個不良類型的術語,你必須更精確地指出你想破壞的東西(這里不是秘密,它是基於每個案例) 。 通過提取子引理,您可能已經刪除了麻煩的依賴關系,現在破壞可以運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.