Consider the function defined below. It's not really important what it does.
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.
I want to prove
Lemma test0: @ScatHUnion_0 nat 0 0 ( @nil nat) = ( @nil (option nat)).
After doing
simpl. unfold eq_rect_r. unfold eq_rect.
the goal is
match mult_n_O 1 in (_ = y) return (t (option nat) y) with
| eq_refl => nil (option nat)
end = nil (option nat)
When trying to finish it off with
apply trans_eq with (Vector.const (@None nat) (1 * 0)); auto.
destruct (mult_n_O 1); auto.
the destruct
doesn't work (see below for error message). However, If I first prove exactly the same goal in a lemma or even with assert
inside the proof, I can apply and solve it, like this:
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.
Can someone explain why this is, and how one should think about this situation when one encounters it?
In Coq 8.4 I get the error
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.
and in Coq 8.5 I get the error
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".