Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) Require Arith_base.
fin n is a convenient way to represent \1 .. n\
fin n can be seen as a n-uplet of unit. F1 is the first element of
the n-uplet. If f is the k-th element of the (n-1)-uplet, FS f is the
(k+1)-th element of the n-uplet.
Author: Pierre Boutillier
Institution: PPS, INRIA 12/2010-01/2012-07/2012
Inductive t : nat -> Set := |F1 : forall {n}, t (S n) |FS : forall {n}, t n -> t (S n). Section SCHEMES. Definition case0 P (p: t 0): P p := match p with | F1 | FS _ => fun devil => False_rect (@IDProp) devil (* subterm !!! *) end. Definition caseS' {n : nat} (p : t (S n)) : forall (P : t (S n) -> Type) (P1 : P F1) (PS : forall (p : t n), P (FS p)), P p := match p with | @F1 k => fun P P1 PS => P1 | FS pp => fun P P1 PS => PS pp end. Definition caseS (P: forall {n}, t (S n) -> Type) (P1: forall n, @P n F1) (PS : forall {n} (p: t n), P (FS p)) {n} (p: t (S n)) : P p := caseS' p P (P1 n) PS. Definition rectS (P: forall {n}, t (S n) -> Type) (P1: forall n, @P n F1) (PS : forall {n} (p: t (S n)), P p -> P (FS p)): forall {n} (p: t (S n)), P p := fix rectS_fix {n} (p: t (S n)): P p:= match p with | @F1 k => P1 k | @FS 0 pp => case0 (fun f => P (FS f)) pp | @FS (S k) pp => PS pp (rectS_fix pp) end. Definition rect2 (P : forall {n} (a b : t n), Type) (H0 : forall n, @P (S n) F1 F1) (H1 : forall {n} (f : t n), P F1 (FS f)) (H2 : forall {n} (f : t n), P (FS f) F1) (HS : forall {n} (f g : t n), P f g -> P (FS f) (FS g)) : forall {n} (a b : t n), P a b := fix rect2_fix {n} (a : t n) {struct a} : forall (b : t n), P a b := match a with | @F1 m => fun (b : t (S m)) => caseS' b (P F1) (H0 _) H1 | @FS m a' => fun (b : t (S m)) => caseS' b (fun b => P (@FS m a') b) (H2 a') (fun b' => HS _ _ (rect2_fix a' b')) end. End SCHEMES. Definition FS_inj {n} (x y: t n) (eq: FS x = FS y): x = y := match eq in _ = a return match a as a' in t m return match m with |0 => Prop |S n' => t n' -> Prop end with F1 => fun _ => True |FS y => fun x' => x' = y end x with eq_refl => eq_refl end.
to_nat f = p iff f is the p{^ th} element of fin m.
Fixpoint to_nat {m} (n : t m) : {i | i < m} :=
match n with
|@F1 j => exist _ 0 (Lt.lt_0_Sn j)
|FS p => match to_nat p with |exist _ i P => exist _ (S i) (Lt.lt_n_S _ _ P) end
end.
of_nat p n answers the p{^ th} element of fin n if p < n or a proof of
p >= n else
Fixpoint of_nat (p n : nat) : (t n) + { exists m, p = n + m } :=
match n with
|0 => inright _ (ex_intro _ p eq_refl)
|S n' => match p with
|0 => inleft _ (F1)
|S p' => match of_nat p' n' with
|inleft f => inleft _ (FS f)
|inright arg => inright _ (match arg with |ex_intro _ m e =>
ex_intro (fun x => S p' = S n' + x) m (f_equal S e) end)
end
end
end.
of_nat_lt p n H answers the p{^ th} element of fin n
it behaves much better than of_nat p n on open term
Fixpoint of_nat_lt {p n : nat} : p < n -> t n := match n with |0 => fun H : p < 0 => False_rect _ (Lt.lt_n_O p H) |S n' => match p with |0 => fun _ => @F1 n' |S p' => fun H => FS (of_nat_lt (Lt.lt_S_n _ _ H)) end end.p, n:nath, h':p < nof_nat_lt h = of_nat_lt h'now rewrite (Peano_dec.le_unique _ _ h h'). Qed.p, n:nath, h':p < nof_nat_lt h = of_nat_lt h'm:natp:t mof_nat_lt (proj2_sig (to_nat p)) = pm:natp:t mof_nat_lt (proj2_sig (to_nat p)) = pn:natF1 = F1n:natp:t nIHp:of_nat_lt (proj2_sig (to_nat p)) = pof_nat_lt (proj2_sig (let (i, P) := to_nat p in exist (fun i0 : nat => i0 < S n) (S i) (Lt.lt_n_S i n P))) = FS preflexivity.n:natF1 = F1n:natp:t nIHp:of_nat_lt (proj2_sig (to_nat p)) = pof_nat_lt (proj2_sig (let (i, P) := to_nat p in exist (fun i0 : nat => i0 < S n) (S i) (Lt.lt_n_S i n P))) = FS pn:natp:t nx:natl:x < nIHp:of_nat_lt l = pFS (of_nat_lt (Lt.lt_S_n x n (Lt.lt_n_S x n l))) = FS pn:natp:t nx:natl:x < nIHp:of_nat_lt l = pof_nat_lt (Lt.lt_S_n x n (Lt.lt_n_S x n l)) = papply of_nat_ext. Qed.n, x:natl:x < nof_nat_lt (Lt.lt_S_n x n (Lt.lt_n_S x n l)) = of_nat_lt lp, n:nath:p < nto_nat (of_nat_lt h) = exist (fun i : nat => i < n) p hp, n:nath:p < nto_nat (of_nat_lt h) = exist (fun i : nat => i < n) p hinduction p; (destruct n ; intros h; [ destruct (Lt.lt_n_O _ h) | cbn]); [ | rewrite (IHp _ (Lt.lt_S_n p n h))]; f_equal; apply Peano_dec.le_unique. Qed.p:natforall (n : nat) (h : p < n), to_nat (of_nat_lt h) = exist (fun i : nat => i < n) p hn:natp, q:t nproj1_sig (to_nat p) = proj1_sig (to_nat q) -> p = qn:natp, q:t nproj1_sig (to_nat p) = proj1_sig (to_nat q) -> p = qn:natp, q:t nH:proj1_sig (to_nat p) = proj1_sig (to_nat q)p = qn:natp, q:t nH:proj1_sig (to_nat p) = proj1_sig (to_nat q)of_nat_lt (proj2_sig (to_nat p)) = of_nat_lt (proj2_sig (to_nat q))n:natp, q:t nnp:nathp:np < nnq:nathq:nq < nH:np = nqof_nat_lt hp = of_nat_lt hqn:natp, q:t nnp, nq:natH:np = nqforall (hp : np < n) (hq : nq < n), of_nat_lt hp = of_nat_lt hqapply of_nat_ext. Qed.n:natp, q:t nnp, nq:natH:np = nqforall hp hq : nq < n, of_nat_lt hp = of_nat_lt hq
weak p f answers a function witch is the identity for the p{^ th} first
element of fin (p + m) and FS (FS .. (FS (f k))) for FS (FS .. (FS k))
with p FSs
Fixpoint weak {m}{n} p (f : t m -> t n) :
t (p + m) -> t (p + n) :=
match p as p' return t (p' + m) -> t (p' + n) with
|0 => f
|S p' => fun x => match x with
|@F1 n' => fun eq : n' = p' + m => F1
|@FS n' y => fun eq : n' = p' + m => FS (weak p' f (eq_rect _ t y _ eq))
end (eq_refl _)
end.
The p{^ th} element of fin m viewed as the p{^ th} element of
fin (m + n)
Fixpoint L {m} n (p : t m) : t (m + n) := match p with |F1 => F1 |FS p' => FS (L n p') end.m, n:natp:t mproj1_sig (to_nat (L n p)) = proj1_sig (to_nat p)m, n:natp:t mproj1_sig (to_nat (L n p)) = proj1_sig (to_nat p)n, n0:natproj1_sig (to_nat (L n F1)) = proj1_sig (to_nat F1)n, n0:natp:t n0IHp:proj1_sig (to_nat (L n p)) = proj1_sig (to_nat p)proj1_sig (to_nat (L n (FS p))) = proj1_sig (to_nat (FS p))reflexivity.n, n0:natproj1_sig (to_nat (L n F1)) = proj1_sig (to_nat F1)n, n0:natp:t n0IHp:proj1_sig (to_nat (L n p)) = proj1_sig (to_nat p)proj1_sig (to_nat (L n (FS p))) = proj1_sig (to_nat (FS p))now destruct (to_nat p). Qed.n, n0:natp:t n0x:natl:x < n0 + nIHp:x = proj1_sig (to_nat p)S (proj1_sig (to_nat p)) = proj1_sig (let (i, P) := to_nat p in exist (fun i0 : nat => i0 < S n0) (S i) (Lt.lt_n_S i n0 P))
The p{^ th} element of fin m viewed as the p{^ th} element of
fin (n + m)
Really really inefficient !!!
m, n:natp:t mt (n + m)m, n:natp:t mt (n + m)m:natp:t mt (0 + m)m, n:natp:t mIHn:t (n + m)t (S n + m)exact p.m:natp:t mt (0 + m)exact ((fix LS k (p: t k) := match p with |@F1 k' => @F1 (S k') |FS p' => FS (LS _ p') end) _ IHn). Defined.m, n:natp:t mIHn:t (n + m)t (S n + m)
The p{^ th} element of fin m viewed as the (n + p){^ th} element of
fin (n + m)
Fixpoint R {m} n (p : t m) : t (n + m) := match n with |0 => p |S n' => FS (R n' p) end.m, n:natp:t mproj1_sig (to_nat (R n p)) = n + proj1_sig (to_nat p)m, n:natp:t mproj1_sig (to_nat (R n p)) = n + proj1_sig (to_nat p)m:natp:t mproj1_sig (to_nat (R 0 p)) = 0 + proj1_sig (to_nat p)m, n:natp:t mIHn:proj1_sig (to_nat (R n p)) = n + proj1_sig (to_nat p)proj1_sig (to_nat (R (S n) p)) = S n + proj1_sig (to_nat p)reflexivity.m:natp:t mproj1_sig (to_nat (R 0 p)) = 0 + proj1_sig (to_nat p)m, n:natp:t mIHn:proj1_sig (to_nat (R n p)) = n + proj1_sig (to_nat p)proj1_sig (to_nat (R (S n) p)) = S n + proj1_sig (to_nat p)now destruct (to_nat p). Qed. Fixpoint depair {m n} (o : t m) (p : t n) : t (m * n) := match o with |@F1 m' => L (m' * n) p |FS o' => R n (depair o' p) end.m, n:natp:t mx:natl:x < n + mIHn:x = n + proj1_sig (to_nat p)S (n + proj1_sig (to_nat p)) = S (n + proj1_sig (to_nat p))m, n:nato:t mp:t nproj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)m, n:nato:t mp:t nproj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)n, n0:natp:t nproj1_sig (to_nat (L (n0 * n) p)) = n * 0 + proj1_sig (to_nat p)n, n0:nato:t n0p:t nIHo:proj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)proj1_sig (to_nat (R n (depair o p))) = n * proj1_sig (let (i, P) := to_nat o in exist (fun i0 : nat => i0 < S n0) (S i) (Lt.lt_n_S i n0 P)) + proj1_sig (to_nat p)n, n0:natp:t nproj1_sig (to_nat (L (n0 * n) p)) = n * 0 + proj1_sig (to_nat p)now rewrite Mult.mult_0_r.n, n0:natp:t nproj1_sig (to_nat p) = n * 0 + proj1_sig (to_nat p)n, n0:nato:t n0p:t nIHo:proj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)proj1_sig (to_nat (R n (depair o p))) = n * proj1_sig (let (i, P) := to_nat o in exist (fun i0 : nat => i0 < S n0) (S i) (Lt.lt_n_S i n0 P)) + proj1_sig (to_nat p)n, n0:nato:t n0p:t nIHo:proj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)n + proj1_sig (to_nat (depair o p)) = n * proj1_sig (let (i, P) := to_nat o in exist (fun i0 : nat => i0 < S n0) (S i) (Lt.lt_n_S i n0 P)) + proj1_sig (to_nat p)n, n0:nato:t n0p:t nIHo:proj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)n + (n * proj1_sig (to_nat o) + proj1_sig (to_nat p)) = n * proj1_sig (let (i, P) := to_nat o in exist (fun i0 : nat => i0 < S n0) (S i) (Lt.lt_n_S i n0 P)) + proj1_sig (to_nat p)n, n0:nato:t n0p:t nIHo:proj1_sig (to_nat (depair o p)) = n * proj1_sig (to_nat o) + proj1_sig (to_nat p)n + n * proj1_sig (to_nat o) + proj1_sig (to_nat p) = n * proj1_sig (let (i, P) := to_nat o in exist (fun i0 : nat => i0 < S n0) (S i) (Lt.lt_n_S i n0 P)) + proj1_sig (to_nat p)now rewrite (Plus.plus_comm n). Qed. Fixpoint eqb {m n} (p : t m) (q : t n) := match p, q with | @F1 m', @F1 n' => EqNat.beq_nat m' n' | FS _, F1 => false | F1, FS _ => false | FS p', FS q' => eqb p' q' end.n, n0:nato:t n0p:t nx:natl:x < n0IHo:proj1_sig (to_nat (depair o p)) = n * proj1_sig (exist (fun i : nat => i < n0) x l) + proj1_sig (to_nat p)n + n * x + proj1_sig (to_nat p) = n * x + n + proj1_sig (to_nat p)forall (m n : nat) (p : t m) (q : t n), eqb p q = true -> m = nforall (m n : nat) (p : t m) (q : t n), eqb p q = true -> m = nn, n0:natH:PeanoNat.Nat.eqb n n0 = truen = n0n, n0:natq:t n0H:false = truen = n0n:natp:t nIHp:forall (n1 : nat) (q : t n1), eqb p q = true -> n = n1n0:natH:false = truen = n0n:natp:t nIHp:forall (n1 : nat) (q0 : t n1), eqb p q0 = true -> n = n1n0:natq:t n0H:eqb p q = truen = n0now apply EqNat.beq_nat_true.n, n0:natH:PeanoNat.Nat.eqb n n0 = truen = n0easy.n, n0:natq:t n0H:false = truen = n0easy.n:natp:t nIHp:forall (n1 : nat) (q : t n1), eqb p q = true -> n = n1n0:natH:false = truen = n0n:natp:t nIHp:forall (n1 : nat) (q0 : t n1), eqb p q0 = true -> n = n1n0:natq:t n0H:eqb p q = truen = n0eassumption. Qed.n:natp:t nIHp:forall (n1 : nat) (q0 : t n1), eqb p q0 = true -> n = n1n0:natq:t n0H:eqb p q = trueeqb p ?q = trueforall (n : nat) (p q : t n), eqb p q = true <-> p = qforall (n : nat) (p q : t n), eqb p q = true <-> p = qn:natPeanoNat.Nat.eqb n n = true <-> F1 = F1n:natf:t nfalse = true <-> F1 = FS fn:natf:t nfalse = true <-> FS f = F1n:natf, g:t nH:eqb f g = true <-> f = geqb f g = true <-> FS f = FS gsplit; intros ; [ reflexivity | now apply EqNat.beq_nat_true_iff ].n:natPeanoNat.Nat.eqb n n = true <-> F1 = F1now split.n:natf:t nfalse = true <-> F1 = FS fnow split.n:natf:t nfalse = true <-> FS f = F1n:natf, g:t nH:eqb f g = true <-> f = geqb f g = true <-> FS f = FS gn:natf, g:t nH:eqb f g = true <-> f = geqb f g = true <-> ?Bn:natf, g:t nH:eqb f g = true <-> f = g?B <-> FS f = FS geassumption.n:natf, g:t nH:eqb f g = true <-> f = geqb f g = true <-> ?Bn:natf, g:t nH:eqb f g = true <-> f = gf = g <-> FS f = FS gn:natf, g:t nH:eqb f g = true <-> f = gf = g -> FS f = FS gn:natf, g:t nH:eqb f g = true <-> f = gFS f = FS g -> f = gintros; now f_equal.n:natf, g:t nH:eqb f g = true <-> f = gf = g -> FS f = FS gapply FS_inj. Qed.n:natf, g:t nH:eqb f g = true <-> f = gFS f = FS g -> f = gn:natx, y:t n{x = y} + {x <> y}n:natx, y:t n{x = y} + {x <> y}n:natx, y:t nH:eqb x y = true{x = y} + {x <> y}n:natx, y:t nH:eqb x y = false{x = y} + {x <> y}left; now apply eqb_eq.n:natx, y:t nH:eqb x y = true{x = y} + {x <> y}n:natx, y:t nH:eqb x y = false{x = y} + {x <> y}n:natx, y:t nH:eqb x y = falsex <> yn:natx, y:t nH:eqb x y = falseHeq:x = yFalsecongruence. Defined.n:natx, y:t nH:eqb x y = falseHeq:eqb x y = trueFalseforall m : nat, t m -> forall n : nat, m = n -> t nrefine (fix cast {m} (v: t m) {struct v} := match v in t m' return forall n, m' = n -> t n with |F1 => fun n => match n with | 0 => fun H => False_rect _ _ | S n' => fun H => F1 end |FS f => fun n => match n with | 0 => fun H => False_rect _ _ | S n' => fun H => FS (cast f n' (f_equal pred H)) end end); discriminate. Defined.forall m : nat, t m -> forall n : nat, m = n -> t n