Library Stdlib.Vectors.Fin
N.B.: This file defines a dependently-type programming view of
bounded integers. Another popular approach is to bundle integers with
a proof of boundedness, thus inheriting integer arithmetic rather than
redefining it on the bounded type. See
https://github.com/coq/stdlib/blob/master/theories/Vectors/Vector.v
for a similar discussion on bounded lists.
An alternative implementation can be found for instance in
https://github.com/math-comp/math-comp/blob/master/mathcomp/ssreflect/fintype.v
One can read more about this type in section 7.4 of this book:
https://zenodo.org/record/4282710.X_q4aGso-yU .
fin n is a 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 (@
ID)
devil 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.
of_nat p n answers the p{^ th} element of fin n if p < n or a proof of
p >= n else
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
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
The p{^ th} element of fin m viewed as the p{^ th} element of
fin (m + n)
The p{^ th} element of fin m viewed as the p{^ th} element of
fin (n + m)
Really really inefficient !!!
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.
Lemma R_sanity {
m}
n (
p :
t m) :
proj1_sig (
to_nat (
R n p))
= n + proj1_sig (
to_nat p).
Lemma R_inj {
m}
n (
p q :
t m) :
R n p = R n q -> p = q.
Lemma L_R_neq n m (
p :
t n) (
q :
t m) :
L m p <> R n q.
Fixpoint case_L_R' {
n m} :
forall (
P :
t (
n + m)
-> Type) (
p :
t (
n + m)),
(forall q,
P (
L m q)
) -> (forall q,
P (
R n q)
) -> P p :=
match n with
| 0 =>
fun P p HL HR =>
HR p
|
S n' =>
fun P p HL HR =>
Fin.caseS' p P
(
HL Fin.F1)
(
fun p' =>
case_L_R' (
fun q =>
P (
Fin.FS q))
p' (
fun q =>
HL (
Fin.FS q))
HR)
end.
Definition case_L_R (
P :
forall n m,
t (
n + m)
-> Type) {
n m} (
p :
t (
n + m)) :
(forall n m (
q :
t n),
P n m (
L m q)
) -> (forall n m (
q :
t m),
P n m (
R n q)
) -> P n m p :=
fun HL HR =>
case_L_R' _ p (
HL _ _) (
HR _ _).
Lemma case_L_R'_L {
n m :
nat} (
P :
Fin.t (
n + m)
-> Type) (
p :
Fin.t n)
HL HR :
case_L_R' P (
Fin.L m p)
HL HR = HL p.
Lemma case_L_R'_R {
n m :
nat} (
P :
Fin.t (
n + m)
-> Type) (
p :
Fin.t m)
HL HR :
case_L_R' P (
Fin.R n p)
HL HR = HR p.
Lemma case_L_R_L (
P :
forall n m,
t (
n + m)
-> Type) {
n m} (
p :
Fin.t n)
HL HR :
case_L_R P (
Fin.L m p)
HL HR = HL _ _ p.
Lemma case_L_R_R (
P :
forall n m,
t (
n + m)
-> Type) {
n m} (
p :
Fin.t m)
HL HR :
case_L_R P (
Fin.R n p)
HL HR = HR _ _ p.
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.
Lemma depair_sanity {
m n} (
o :
t m) (
p :
t n) :
proj1_sig (
to_nat (
depair o p))
= n * (proj1_sig (
to_nat o)
) + (proj1_sig (
to_nat p)
).
Fixpoint eqb {
m n} (
p :
t m) (
q :
t n) :=
match p,
q with
| @
F1 m', @
F1 n' =>
Nat.eqb m' n'
|
FS _,
F1 =>
false
|
F1,
FS _ =>
false
|
FS p',
FS q' =>
eqb p' q'
end.
Lemma eqb_nat_eq :
forall m n (
p :
t m) (
q :
t n),
eqb p q = true -> m = n.
Lemma eqb_eq :
forall n (
p q :
t n),
eqb p q = true <-> p = q.
Lemma eq_dec {
n} (
x y :
t n):
{x = y} + {x <> y}.
Definition cast:
forall {
m} (
v:
t m) {
n},
m = n -> t n.