Рассмотрим функцию, определенную ниже. Не важно, что он делает.Почему я могу иногда доказывать цель через лемм, но не напрямую?
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".
Вам не нужно убеждать Coq, что '' 0 = 1 * 0'', это совершенно верно (просто подтвердите это '' рефлексивностью''). Проблема в вашем случае после вашего '' simple'', вы в конечном итоге проверяете * доказательство * этого факта, а именно '' mult_n_0 1'', что непрозрачно. Правила разворачивания Coq требуют непрозрачного термина, чтобы иметь возможность выполнять инструкцию '' match''. Вот почему просто застрял на стадии '' eq_rect_t'' и больше не раскрывается. Сделав это доказательство '' Defined'', вы удалите эту проблему, и упрощение может продолжаться (вот почему '' рефлексивность' работает в конце). – Vinz
Да, но как я могу убедить, что средство проверки типов использует рефлексивность? – larsr
Я только что увидел ваш вопрос в списке рассылки coq-club, и я, возможно, пропустил эту проблему: «' 0 = 1 * 0'' тривиально доказана рефлексивностью, но '' forall P1 P2: 0 = 1 * 0 , P1 = P2'', что означает «для любых двух доказательств этого факта * доказательства * равны», чем вы не можете сделать это так тривиально, вам нужно свойство (true on nat), называемое «Уникальность удостоверения личности» «; В Coq доказательства одного утверждения равенства не обязательно равны. Но это верно, по крайней мере, для доказательства равенства на типах, которые разрешимы. – Vinz