Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Simon Spies
stdpp
Commits
487cdead
Commit
487cdead
authored
Feb 01, 2013
by
Robbert Krebbers
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Some minor cleanup, and more lemmas on prefix/postfixes of lists.
parent
a89a1e98
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
349 additions
and
92 deletions
+349
-92
theories/base.v
theories/base.v
+9
-7
theories/decidable.v
theories/decidable.v
+18
-11
theories/list.v
theories/list.v
+273
-60
theories/numbers.v
theories/numbers.v
+44
-9
theories/tactics.v
theories/tactics.v
+5
-5
No files found.
theories/base.v
View file @
487cdead
...
...
@@ -290,7 +290,7 @@ Notation "(≫=)" := (λ m f, mbind f m) (only parsing) : C_scope.
Notation
"x ← y ; z"
:
=
(
y
≫
=
(
λ
x
:
_
,
z
))
(
at
level
65
,
only
parsing
,
next
at
level
35
,
right
associativity
)
:
C_scope
.
Infix
"<$>"
:
=
fmap
(
at
level
6
5
,
right
associativity
)
:
C_scope
.
Infix
"<$>"
:
=
fmap
(
at
level
6
0
,
right
associativity
)
:
C_scope
.
Class
MGuard
(
M
:
Type
→
Type
)
:
=
mguard
:
∀
P
{
dec
:
Decision
P
}
{
A
},
M
A
→
M
A
.
...
...
@@ -425,6 +425,10 @@ Arguments left_absorb {_ _} _ _ {_} _.
Arguments
right_absorb
{
_
_
}
_
_
{
_
}
_
.
Arguments
anti_symmetric
{
_
}
_
{
_
}
_
_
_
_
.
Instance
:
Commutative
(
↔
)
(@
eq
A
).
Proof
.
red
.
intuition
.
Qed
.
Instance
:
Commutative
(
↔
)
(
λ
x
y
,
@
eq
A
y
x
).
Proof
.
red
.
intuition
.
Qed
.
Instance
:
Commutative
(
↔
)
(
↔
).
Proof
.
red
.
intuition
.
Qed
.
Instance
:
Commutative
(
↔
)
(
∧
).
...
...
@@ -672,13 +676,11 @@ Section prod_relation.
End
prod_relation
.
(** ** Other *)
Definition
lift
_relation
{
A
B
}
(
R
:
relation
A
)
Definition
proj
_relation
{
A
B
}
(
R
:
relation
A
)
(
f
:
B
→
A
)
:
relation
B
:
=
λ
x
y
,
R
(
f
x
)
(
f
y
).
Definition
lift_relation_equivalence
{
A
B
}
(
R
:
relation
A
)
(
f
:
B
→
A
)
:
Equivalence
R
→
Equivalence
(
lift_relation
R
f
).
Proof
.
unfold
lift_relation
.
firstorder
auto
.
Qed
.
Hint
Extern
0
(
Equivalence
(
lift_relation
_
_
))
=>
eapply
@
lift_relation_equivalence
:
typeclass_instances
.
Definition
proj_relation_equivalence
{
A
B
}
(
R
:
relation
A
)
(
f
:
B
→
A
)
:
Equivalence
R
→
Equivalence
(
proj_relation
R
f
).
Proof
.
unfold
proj_relation
.
firstorder
auto
.
Qed
.
Instance
:
∀
A
B
(
x
:
B
),
Commutative
(=)
(
λ
_
_
:
A
,
x
).
Proof
.
red
.
trivial
.
Qed
.
...
...
theories/decidable.v
View file @
487cdead
...
...
@@ -46,6 +46,17 @@ Ltac solve_decision := intros; first
[
solve_trivial_decision
|
unfold
Decision
;
decide
equality
;
solve_trivial_decision
].
(** The following combinators are useful to create Decision proofs in
combination with the [refine] tactic. *)
Notation
cast_if
S
:
=
(
if
S
then
left
_
else
right
_
).
Notation
cast_if_and
S1
S2
:
=
(
if
S1
then
cast_if
S2
else
right
_
).
Notation
cast_if_and3
S1
S2
S3
:
=
(
if
S1
then
cast_if_and
S2
S3
else
right
_
).
Notation
cast_if_and4
S1
S2
S3
S4
:
=
(
if
S1
then
cast_if_and3
S2
S3
S4
else
right
_
).
Notation
cast_if_or
S1
S2
:
=
(
if
S1
then
left
_
else
cast_if
S2
).
Notation
cast_if_not_or
S1
S2
:
=
(
if
S1
then
cast_if
S2
else
left
_
).
Notation
cast_if_not
S
:
=
(
if
S
then
right
_
else
left
_
).
(** We can convert decidable propositions to booleans. *)
Definition
bool_decide
(
P
:
Prop
)
{
dec
:
Decision
P
}
:
bool
:
=
if
dec
then
true
else
false
.
...
...
@@ -66,8 +77,7 @@ Definition proj2_dsig `{∀ x : A, Decision (P x)} (x : dsig P) : P (`x) :=
bool_decide_unpack
_
(
proj2_sig
x
).
Definition
dexist
`
{
∀
x
:
A
,
Decision
(
P
x
)}
(
x
:
A
)
(
p
:
P
x
)
:
dsig
P
:
=
x
↾
bool_decide_pack
_
p
.
Lemma
dsig_eq
{
A
}
(
P
:
A
→
Prop
)
{
dec
:
∀
x
,
Decision
(
P
x
)}
Lemma
dsig_eq
`
(
P
:
A
→
Prop
)
`
{
∀
x
,
Decision
(
P
x
)}
(
x
y
:
dsig
P
)
:
x
=
y
↔
`
x
=
`
y
.
Proof
.
split
.
...
...
@@ -78,16 +88,13 @@ Proof.
+
by
intros
[]
[].
+
done
.
Qed
.
Lemma
dexists_proj1
`
(
P
:
A
→
Prop
)
`
{
∀
x
,
Decision
(
P
x
)}
(
x
:
dsig
P
)
p
:
dexist
(
`
x
)
p
=
x
.
Proof
.
by
apply
dsig_eq
.
Qed
.
(** The following combinators are useful to create Decision proofs in
combination with the [refine] tactic. *)
Notation
cast_if
S
:
=
(
if
S
then
left
_
else
right
_
).
Notation
cast_if_and
S1
S2
:
=
(
if
S1
then
cast_if
S2
else
right
_
).
Notation
cast_if_and3
S1
S2
S3
:
=
(
if
S1
then
cast_if_and
S2
S3
else
right
_
).
Notation
cast_if_and4
S1
S2
S3
S4
:
=
(
if
S1
then
cast_if_and3
S2
S3
S4
else
right
_
).
Notation
cast_if_or
S1
S2
:
=
(
if
S1
then
left
_
else
cast_if
S2
).
Notation
cast_if_not
S
:
=
(
if
S
then
right
_
else
left
_
).
Global
Instance
dsig_eq_dec
`
(
P
:
A
→
Prop
)
`
{
∀
x
,
Decision
(
P
x
)}
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}
(
x
y
:
dsig
P
)
:
Decision
(
x
=
y
).
Proof
.
refine
(
cast_if
(
decide
(
`
x
=
`
y
)))
;
by
rewrite
dsig_eq
.
Defined
.
(** * Instances of Decision *)
(** Instances of [Decision] for operators of propositional logic. *)
...
...
theories/list.v
View file @
487cdead
...
...
@@ -105,10 +105,26 @@ Fixpoint resize {A} (n : nat) (y : A) (l : list A) : list A :=
end
.
Arguments
resize
{
_
}
!
_
_
!
_
.
(** The predicate [prefix_of] holds if the first list is a prefix of the second.
The predicate [suffix_of] holds if the first list is a suffix of the second. *)
Definition
prefix_of
{
A
}
(
l1
l2
:
list
A
)
:
Prop
:
=
∃
k
,
l2
=
l1
++
k
.
(** The predicate [suffix_of] holds if the first list is a suffix of the second.
The predicate [prefix_of] holds if the first list is a prefix of the second. *)
Definition
suffix_of
{
A
}
(
l1
l2
:
list
A
)
:
Prop
:
=
∃
k
,
l2
=
k
++
l1
.
Definition
prefix_of
{
A
}
(
l1
l2
:
list
A
)
:
Prop
:
=
∃
k
,
l2
=
l1
++
k
.
Definition
max_prefix_of
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}
:
list
A
→
list
A
→
list
A
*
list
A
*
list
A
:
=
fix
go
l1
l2
:
=
match
l1
,
l2
with
|
[],
l2
=>
([],
l2
,
[])
|
l1
,
[]
=>
(
l1
,
[],
[])
|
x1
::
l1
,
x2
::
l2
=>
if
decide_rel
(=)
x1
x2
then
snd_map
(
x1
::
)
(
go
l1
l2
)
else
(
x1
::
l1
,
x2
::
l2
,
[])
end
.
Definition
max_suffix_of
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}
(
l1
l2
:
list
A
)
:
list
A
*
list
A
*
list
A
:
=
match
max_prefix_of
(
reverse
l1
)
(
reverse
l2
)
with
|
(
k1
,
k2
,
k3
)
=>
(
reverse
k1
,
reverse
k2
,
reverse
k3
)
end
.
(** * Tactics on lists *)
Lemma
cons_inv
{
A
}
(
l1
l2
:
list
A
)
x1
x2
:
...
...
@@ -122,7 +138,7 @@ Tactic Notation "discriminate_list_equality" hyp(H) :=
repeat
(
simpl
in
H
||
rewrite
app_length
in
H
)
;
exfalso
;
lia
.
Tactic
Notation
"discriminate_list_equality"
:
=
repeat_on_hyps
(
fun
H
=>
discriminate_list_equality
H
).
solve
[
repeat_on_hyps
(
fun
H
=>
discriminate_list_equality
H
)
]
.
(** The tactic [simplify_list_equality] simplifies assumptions involving
equalities on lists. *)
...
...
@@ -153,6 +169,12 @@ Global Instance: ∀ k : list A, Injective (=) (=) (k ++).
Proof
.
intros
???.
apply
app_inv_head
.
Qed
.
Global
Instance
:
∀
k
:
list
A
,
Injective
(=)
(=)
(++
k
).
Proof
.
intros
???.
apply
app_inv_tail
.
Qed
.
Global
Instance
:
Associative
(=)
(@
app
A
).
Proof
.
intros
???.
apply
app_assoc
.
Qed
.
Global
Instance
:
LeftId
(=)
[]
(@
app
A
).
Proof
.
done
.
Qed
.
Global
Instance
:
RightId
(=)
[]
(@
app
A
).
Proof
.
intro
.
apply
app_nil_r
.
Qed
.
Lemma
app_inj
(
l1
k1
l2
k2
:
list
A
)
:
length
l1
=
length
k1
→
...
...
@@ -532,6 +554,8 @@ Qed.
Lemma
reverse_nil
:
reverse
[]
=
@
nil
A
.
Proof
.
done
.
Qed
.
Lemma
reverse_singleton
(
x
:
A
)
:
reverse
[
x
]
=
[
x
].
Proof
.
done
.
Qed
.
Lemma
reverse_cons
(
l
:
list
A
)
x
:
reverse
(
x
::
l
)
=
reverse
l
++
[
x
].
Proof
.
unfold
reverse
.
by
rewrite
<-!
rev_alt
.
Qed
.
Lemma
reverse_snoc
(
l
:
list
A
)
x
:
reverse
(
l
++
[
x
])
=
x
::
reverse
l
.
...
...
@@ -704,7 +728,7 @@ Lemma resize_le (l : list A) n x :
resize
n
x
l
=
take
n
l
.
Proof
.
intros
.
rewrite
resize_spec
,
(
proj2
(
NPeano
.
Nat
.
sub_0_le
_
_
))
by
done
.
simpl
.
by
rewrite
app_nil_r
.
simpl
.
by
rewrite
(
right_id
[]
(++))
.
Qed
.
Lemma
resize_all
(
l
:
list
A
)
x
:
...
...
@@ -720,7 +744,7 @@ Lemma resize_plus (l : list A) n m x :
Proof
.
revert
n
m
.
induction
l
;
intros
[|?]
[|?]
;
simpl
;
f_equal
;
auto
.
*
by
rewrite
plus_0_r
,
app_nil_r
.
*
by
rewrite
plus_0_r
,
(
right_id
[]
(++))
.
*
by
rewrite
replicate_plus
.
Qed
.
Lemma
resize_plus_eq
(
l
:
list
A
)
n
m
x
:
...
...
@@ -743,7 +767,7 @@ Lemma resize_app_ge (l1 l2 : list A) n x :
resize
n
x
(
l1
++
l2
)
=
l1
++
resize
(
n
-
length
l1
)
x
l2
.
Proof
.
intros
.
rewrite
!
resize_spec
,
take_app_ge
,
app_
assoc
by
done
.
rewrite
!
resize_spec
,
take_app_ge
,
(
assoc
iative
(++))
by
done
.
do
2
f_equal
.
rewrite
app_length
.
lia
.
Qed
.
...
...
@@ -1205,18 +1229,21 @@ Section prefix_postfix.
Global
Instance
:
PreOrder
(@
prefix_of
A
).
Proof
.
split
.
*
intros
?.
eexists
[].
by
rewrite
app_nil_r
.
*
intros
?.
eexists
[].
by
rewrite
(
right_id
[]
(++))
.
*
intros
???
[
k1
?]
[
k2
?].
exists
(
k1
++
k2
).
subst
.
by
rewrite
app_
assoc
.
exists
(
k1
++
k2
).
subst
.
by
rewrite
(
assoc
iative
(++))
.
Qed
.
Lemma
prefix_of_nil
(
l
:
list
A
)
:
prefix_of
[]
l
.
Proof
.
by
exists
l
.
Qed
.
Lemma
prefix_of_nil_not
x
(
l
:
list
A
)
:
¬
prefix_of
(
x
::
l
)
[].
Proof
.
by
intros
[
k
E
].
Qed
.
Lemma
prefix_of_cons
x
y
(
l1
l2
:
list
A
)
:
Lemma
prefix_of_cons
x
(
l1
l2
:
list
A
)
:
prefix_of
l1
l2
→
prefix_of
(
x
::
l1
)
(
x
::
l2
).
Proof
.
intros
[
k
E
].
exists
k
.
by
subst
.
Qed
.
Lemma
prefix_of_cons_alt
x
y
(
l1
l2
:
list
A
)
:
x
=
y
→
prefix_of
l1
l2
→
prefix_of
(
x
::
l1
)
(
y
::
l2
).
Proof
.
intro
s
?
[
k
E
].
exists
k
.
by
subst
.
Qed
.
Proof
.
intro
.
subst
.
apply
prefix_of_cons
.
Qed
.
Lemma
prefix_of_cons_inv_1
x
y
(
l1
l2
:
list
A
)
:
prefix_of
(
x
::
l1
)
(
y
::
l2
)
→
x
=
y
.
Proof
.
intros
[
k
E
].
by
injection
E
.
Qed
.
...
...
@@ -1224,21 +1251,129 @@ Section prefix_postfix.
prefix_of
(
x
::
l1
)
(
y
::
l2
)
→
prefix_of
l1
l2
.
Proof
.
intros
[
k
E
].
exists
k
.
by
injection
E
.
Qed
.
Lemma
prefix_of_app
k
(
l1
l2
:
list
A
)
:
prefix_of
l1
l2
→
prefix_of
(
k
++
l1
)
(
k
++
l2
).
Proof
.
intros
[
k'
?].
subst
.
exists
k'
.
by
rewrite
(
associative
(++)).
Qed
.
Lemma
prefix_of_app_alt
k1
k2
(
l1
l2
:
list
A
)
:
k1
=
k2
→
prefix_of
l1
l2
→
prefix_of
(
k1
++
l1
)
(
k2
++
l2
).
Proof
.
intro
.
subst
.
apply
prefix_of_app
.
Qed
.
Lemma
prefix_of_app_l
(
l1
l2
l3
:
list
A
)
:
prefix_of
(
l1
++
l3
)
l2
→
prefix_of
l1
l2
.
Proof
.
intros
[
k
?].
red
.
exists
(
l3
++
k
).
subst
.
by
rewrite
<-
app_assoc
.
Qed
.
Proof
.
intros
[
k
?].
red
.
exists
(
l3
++
k
).
subst
.
by
rewrite
<-(
associative
(++)).
Qed
.
Lemma
prefix_of_app_r
(
l1
l2
l3
:
list
A
)
:
prefix_of
l1
l2
→
prefix_of
l1
(
l2
++
l3
).
Proof
.
intros
[
k
?].
exists
(
k
++
l3
).
subst
.
by
rewrite
app_assoc
.
Qed
.
Proof
.
intros
[
k
?].
exists
(
k
++
l3
).
subst
.
by
rewrite
(
associative
(++)).
Qed
.
Lemma
prefix_of_length
(
l1
l2
:
list
A
)
:
prefix_of
l1
l2
→
length
l1
≤
length
l2
.
Proof
.
intros
[??].
subst
.
rewrite
app_length
.
lia
.
Qed
.
Lemma
prefix_of_snoc_not
(
l
:
list
A
)
x
:
¬
prefix_of
(
l
++
[
x
])
l
.
Proof
.
intros
[??].
discriminate_list_equality
.
Qed
.
Global
Instance
:
PreOrder
(@
suffix_of
A
).
Proof
.
split
.
*
intros
?.
by
eexists
[].
*
intros
???
[
k1
?]
[
k2
?].
exists
(
k2
++
k1
).
subst
.
by
rewrite
app_
assoc
.
exists
(
k2
++
k1
).
subst
.
by
rewrite
(
assoc
iative
(++))
.
Qed
.
Global
Instance
prefix_of_dec
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}
:
∀
l1
l2
:
list
A
,
Decision
(
prefix_of
l1
l2
)
:
=
fix
go
l1
l2
:
=
match
l1
,
l2
return
{
prefix_of
l1
l2
}
+
{
¬
prefix_of
l1
l2
}
with
|
[],
_
=>
left
(
prefix_of_nil
_
)
|
_
,
[]
=>
right
(
prefix_of_nil_not
_
_
)
|
x
::
l1
,
y
::
l2
=>
match
decide_rel
(=)
x
y
with
|
left
Exy
=>
match
go
l1
l2
with
|
left
Hl1l2
=>
left
(
prefix_of_cons_alt
_
_
_
_
Exy
Hl1l2
)
|
right
Hl1l2
=>
right
(
Hl1l2
∘
prefix_of_cons_inv_2
_
_
_
_
)
end
|
right
Exy
=>
right
(
Exy
∘
prefix_of_cons_inv_1
_
_
_
_
)
end
end
.
Section
max_prefix_of
.
Context
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}.
Lemma
max_prefix_of_fst
(
l1
l2
:
list
A
)
:
l1
=
snd
(
max_prefix_of
l1
l2
)
++
fst
(
fst
(
max_prefix_of
l1
l2
)).
Proof
.
revert
l2
.
induction
l1
;
intros
[|??]
;
simpl
;
repeat
case_decide
;
simpl
;
f_equal
;
auto
.
Qed
.
Lemma
max_prefix_of_fst_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_prefix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
l1
=
k3
++
k1
.
Proof
.
intro
.
pose
proof
(
max_prefix_of_fst
l1
l2
).
by
destruct
(
max_prefix_of
l1
l2
)
as
[[]?]
;
simplify_equality
.
Qed
.
Lemma
max_prefix_of_fst_prefix
(
l1
l2
:
list
A
)
:
prefix_of
(
snd
(
max_prefix_of
l1
l2
))
l1
.
Proof
.
eexists
.
apply
max_prefix_of_fst
.
Qed
.
Lemma
max_prefix_of_fst_prefix_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_prefix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
prefix_of
k3
l1
.
Proof
.
eexists
.
eauto
using
max_prefix_of_fst_alt
.
Qed
.
Lemma
max_prefix_of_snd
(
l1
l2
:
list
A
)
:
l2
=
snd
(
max_prefix_of
l1
l2
)
++
snd
(
fst
(
max_prefix_of
l1
l2
)).
Proof
.
revert
l2
.
induction
l1
;
intros
[|??]
;
simpl
;
repeat
case_decide
;
simpl
;
f_equal
;
auto
.
Qed
.
Lemma
max_prefix_of_snd_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_prefix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
l2
=
k3
++
k2
.
Proof
.
intro
.
pose
proof
(
max_prefix_of_snd
l1
l2
).
by
destruct
(
max_prefix_of
l1
l2
)
as
[[]?]
;
simplify_equality
.
Qed
.
Lemma
max_prefix_of_snd_prefix
(
l1
l2
:
list
A
)
:
prefix_of
(
snd
(
max_prefix_of
l1
l2
))
l2
.
Proof
.
eexists
.
apply
max_prefix_of_snd
.
Qed
.
Lemma
max_prefix_of_snd_prefix_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_prefix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
prefix_of
k3
l2
.
Proof
.
eexists
.
eauto
using
max_prefix_of_snd_alt
.
Qed
.
Lemma
max_prefix_of_max
(
l1
l2
:
list
A
)
k
:
prefix_of
k
l1
→
prefix_of
k
l2
→
prefix_of
k
(
snd
(
max_prefix_of
l1
l2
)).
Proof
.
intros
[
l1'
?]
[
l2'
?].
subst
.
by
induction
k
;
simpl
;
repeat
case_decide
;
simpl
;
auto
using
prefix_of_nil
,
prefix_of_cons
.
Qed
.
Lemma
max_prefix_of_max_alt
(
l1
l2
:
list
A
)
k1
k2
k3
k
:
max_prefix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
prefix_of
k
l1
→
prefix_of
k
l2
→
prefix_of
k
k3
.
Proof
.
intro
.
pose
proof
(
max_prefix_of_max
l1
l2
k
).
by
destruct
(
max_prefix_of
l1
l2
)
as
[[]?]
;
simplify_equality
.
Qed
.
Lemma
max_prefix_of_max_snoc
(
l1
l2
:
list
A
)
k1
k2
k3
x1
x2
:
max_prefix_of
l1
l2
=
(
x1
::
k1
,
x2
::
k2
,
k3
)
→
x1
≠
x2
.
Proof
.
intros
Hl
?.
subst
.
destruct
(
prefix_of_snoc_not
k3
x2
).
eapply
max_prefix_of_max_alt
;
eauto
.
*
rewrite
(
max_prefix_of_fst_alt
_
_
_
_
_
Hl
).
apply
prefix_of_app
,
prefix_of_cons
,
prefix_of_nil
.
*
rewrite
(
max_prefix_of_snd_alt
_
_
_
_
_
Hl
).
apply
prefix_of_app
,
prefix_of_cons
,
prefix_of_nil
.
Qed
.
End
max_prefix_of
.
Lemma
prefix_suffix_reverse
(
l1
l2
:
list
A
)
:
prefix_of
l1
l2
↔
suffix_of
(
reverse
l1
)
(
reverse
l2
).
Proof
.
...
...
@@ -1251,15 +1386,24 @@ Section prefix_postfix.
Proof
.
by
rewrite
prefix_suffix_reverse
,
!
reverse_involutive
.
Qed
.
Lemma
suffix_of_nil
(
l
:
list
A
)
:
suffix_of
[]
l
.
Proof
.
exists
l
.
by
rewrite
app_nil_r
.
Qed
.
Proof
.
exists
l
.
by
rewrite
(
right_id
[]
(++))
.
Qed
.
Lemma
suffix_of_nil_inv
(
l
:
list
A
)
:
suffix_of
l
[]
→
l
=
[].
Proof
.
by
intros
[[|?]
?]
;
simplify_list_equality
.
Qed
.
Lemma
suffix_of_cons_nil_inv
x
(
l
:
list
A
)
:
¬
suffix_of
(
x
::
l
)
[].
Proof
.
by
intros
[[]
?].
Qed
.
Lemma
suffix_of_snoc
(
l1
l2
:
list
A
)
x
:
suffix_of
l1
l2
→
suffix_of
(
l1
++
[
x
])
(
l2
++
[
x
]).
Proof
.
intros
[
k
E
].
exists
k
.
subst
.
by
rewrite
(
associative
(++)).
Qed
.
Lemma
suffix_of_snoc_alt
x
y
(
l1
l2
:
list
A
)
:
x
=
y
→
suffix_of
l1
l2
→
suffix_of
(
l1
++
[
x
])
(
l2
++
[
y
]).
Proof
.
intro
.
subst
.
apply
suffix_of_snoc
.
Qed
.
Lemma
suffix_of_app
(
l1
l2
k
:
list
A
)
:
suffix_of
l1
l2
→
suffix_of
(
l1
++
k
)
(
l2
++
k
).
Proof
.
intros
[
k'
E
].
exists
k'
.
subst
.
by
rewrite
app_assoc
.
Qed
.
Proof
.
intros
[
k'
E
].
exists
k'
.
subst
.
by
rewrite
(
associative
(++)).
Qed
.
Lemma
suffix_of_app_alt
(
l1
l2
k1
k2
:
list
A
)
:
k1
=
k2
→
suffix_of
l1
l2
→
suffix_of
(
l1
++
k1
)
(
l2
++
k2
).
Proof
.
intro
.
subst
.
apply
suffix_of_app
.
Qed
.
Lemma
suffix_of_snoc_inv_1
x
y
(
l1
l2
:
list
A
)
:
suffix_of
(
l1
++
[
x
])
(
l2
++
[
y
])
→
x
=
y
.
...
...
@@ -1276,17 +1420,25 @@ Section prefix_postfix.
Lemma
suffix_of_cons_l
(
l1
l2
:
list
A
)
x
:
suffix_of
(
x
::
l1
)
l2
→
suffix_of
l1
l2
.
Proof
.
intros
[
k
?].
exists
(
k
++
[
x
]).
subst
.
by
rewrite
<-
app_assoc
.
Qed
.
Proof
.
intros
[
k
?].
exists
(
k
++
[
x
]).
subst
.
by
rewrite
<-(
associative
(++)).
Qed
.
Lemma
suffix_of_app_l
(
l1
l2
l3
:
list
A
)
:
suffix_of
(
l3
++
l1
)
l2
→
suffix_of
l1
l2
.
Proof
.
intros
[
k
?].
exists
(
k
++
l3
).
subst
.
by
rewrite
<-
app_assoc
.
Qed
.
suffix_of
(
l3
++
l1
)
l2
→
suffix_of
l1
l2
.
Proof
.
intros
[
k
?].
exists
(
k
++
l3
).
subst
.
by
rewrite
<-(
associative
(++)).
Qed
.
Lemma
suffix_of_cons_r
(
l1
l2
:
list
A
)
x
:
suffix_of
l1
l2
→
suffix_of
l1
(
x
::
l2
).
Proof
.
intros
[
k
?].
exists
(
x
::
k
).
by
subst
.
Qed
.
Lemma
suffix_of_app_r
(
l1
l2
l3
:
list
A
)
:
suffix_of
l1
l2
→
suffix_of
l1
(
l3
++
l2
).
Proof
.
intros
[
k
?].
exists
(
l3
++
k
).
subst
.
by
rewrite
app_assoc
.
Qed
.
Proof
.
intros
[
k
?].
exists
(
l3
++
k
).
subst
.
by
rewrite
(
associative
(++)).
Qed
.
Lemma
suffix_of_cons_inv
(
l1
l2
:
list
A
)
x
y
:
suffix_of
(
x
::
l1
)
(
y
::
l2
)
→
...
...
@@ -1297,44 +1449,98 @@ Section prefix_postfix.
*
right
.
simplify_equality
.
by
apply
suffix_of_app_r
.
Qed
.
Lemma
suffix_of_length
(
l1
l2
:
list
A
)
:
suffix_of
l1
l2
→
length
l1
≤
length
l2
.
Proof
.
intros
[??].
subst
.
rewrite
app_length
.
lia
.
Qed
.
Lemma
suffix_of_cons_not
x
(
l
:
list
A
)
:
¬
suffix_of
(
x
::
l
)
l
.
Proof
.
intros
[??].
discriminate_list_equality
.
Qed
.
Context
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}.
Fixpoint
strip_prefix
(
l1
l2
:
list
A
)
:
list
A
*
(
list
A
*
list
A
)
:
=
match
l1
,
l2
with
|
[],
l2
=>
([],
([],
l2
))
|
l1
,
[]
=>
([],
(
l1
,
[]))
|
x
::
l1
,
y
::
l2
=>
if
decide_rel
(=)
x
y
then
fst_map
(
x
::
)
(
strip_prefix
l1
l2
)
else
([],
(
x
::
l1
,
y
::
l2
))
end
.
Global
Instance
prefix_of_dec
:
∀
l1
l2
:
list
A
,
Decision
(
prefix_of
l1
l2
)
:
=
fix
go
l1
l2
:
=
match
l1
,
l2
return
{
prefix_of
l1
l2
}
+
{
¬
prefix_of
l1
l2
}
with
|
[],
_
=>
left
(
prefix_of_nil
_
)
|
_
,
[]
=>
right
(
prefix_of_nil_not
_
_
)
|
x
::
l1
,
y
::
l2
=>
match
decide_rel
(=)
x
y
with
|
left
Exy
=>
match
go
l1
l2
with
|
left
Hl1l2
=>
left
(
prefix_of_cons
_
_
_
_
Exy
Hl1l2
)
|
right
Hl1l2
=>
right
(
Hl1l2
∘
prefix_of_cons_inv_2
_
_
_
_
)
end
|
right
Exy
=>
right
(
Exy
∘
prefix_of_cons_inv_1
_
_
_
_
)
end
end
.
Global
Instance
suffix_of_dec
(
l1
l2
:
list
A
)
:
Decision
(
suffix_of
l1
l2
).
Global
Instance
suffix_of_dec
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}
(
l1
l2
:
list
A
)
:
Decision
(
suffix_of
l1
l2
).
Proof
.
refine
(
cast_if
(
decide_rel
prefix_of
(
reverse
l1
)
(
reverse
l2
)))
;
abstract
(
by
rewrite
suffix_prefix_reverse
).
Defined
.
Section
max_suffix_of
.
Context
`
{
∀
x
y
:
A
,
Decision
(
x
=
y
)}.
Lemma
max_suffix_of_fst
(
l1
l2
:
list
A
)
:
l1
=
fst
(
fst
(
max_suffix_of
l1
l2
))
++
snd
(
max_suffix_of
l1
l2
).
Proof
.
rewrite
<-(
reverse_involutive
l1
)
at
1
.
rewrite
(
max_prefix_of_fst
(
reverse
l1
)
(
reverse
l2
)).
unfold
max_suffix_of
.
destruct
(
max_prefix_of
(
reverse
l1
)
(
reverse
l2
))
as
((?&?)&?)
;
simpl
.
by
rewrite
reverse_app
.
Qed
.
Lemma
max_suffix_of_fst_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_suffix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
l1
=
k1
++
k3
.
Proof
.
intro
.
pose
proof
(
max_suffix_of_fst
l1
l2
).
by
destruct
(
max_suffix_of
l1
l2
)
as
[[]?]
;
simplify_equality
.
Qed
.
Lemma
max_suffix_of_fst_suffix
(
l1
l2
:
list
A
)
:
suffix_of
(
snd
(
max_suffix_of
l1
l2
))
l1
.
Proof
.
eexists
.
apply
max_suffix_of_fst
.
Qed
.
Lemma
max_suffix_of_fst_suffix_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_suffix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
suffix_of
k3
l1
.
Proof
.
eexists
.
eauto
using
max_suffix_of_fst_alt
.
Qed
.
Lemma
max_suffix_of_snd
(
l1
l2
:
list
A
)
:
l2
=
snd
(
fst
(
max_suffix_of
l1
l2
))
++
snd
(
max_suffix_of
l1
l2
).
Proof
.
rewrite
<-(
reverse_involutive
l2
)
at
1
.
rewrite
(
max_prefix_of_snd
(
reverse
l1
)
(
reverse
l2
)).
unfold
max_suffix_of
.
destruct
(
max_prefix_of
(
reverse
l1
)
(
reverse
l2
))
as
((?&?)&?)
;
simpl
.
by
rewrite
reverse_app
.
Qed
.
Lemma
max_suffix_of_snd_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_suffix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
l2
=
k2
++
k3
.
Proof
.
intro
.
pose
proof
(
max_suffix_of_snd
l1
l2
).
by
destruct
(
max_suffix_of
l1
l2
)
as
[[]?]
;
simplify_equality
.
Qed
.
Lemma
max_suffix_of_snd_suffix
(
l1
l2
:
list
A
)
:
suffix_of
(
snd
(
max_suffix_of
l1
l2
))
l2
.
Proof
.
eexists
.
apply
max_suffix_of_snd
.
Qed
.
Lemma
max_suffix_of_snd_suffix_alt
(
l1
l2
:
list
A
)
k1
k2
k3
:
max_suffix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
suffix_of
k3
l2
.
Proof
.
eexists
.
eauto
using
max_suffix_of_snd_alt
.
Qed
.
Lemma
max_suffix_of_max
(
l1
l2
:
list
A
)
k
:
suffix_of
k
l1
→
suffix_of
k
l2
→
suffix_of
k
(
snd
(
max_suffix_of
l1
l2
)).
Proof
.
generalize
(
max_prefix_of_max
(
reverse
l1
)
(
reverse
l2
)).
rewrite
!
suffix_prefix_reverse
.
unfold
max_suffix_of
.
destruct
(
max_prefix_of
(
reverse
l1
)
(
reverse
l2
))
as
((?&?)&?)
;
simpl
.
rewrite
reverse_involutive
.
auto
.
Qed
.
Lemma
max_suffix_of_max_alt
(
l1
l2
:
list
A
)
k1
k2
k3
k
:
max_suffix_of
l1
l2
=
(
k1
,
k2
,
k3
)
→
suffix_of
k
l1
→
suffix_of
k
l2
→
suffix_of
k
k3
.
Proof
.
intro
.
pose
proof
(
max_suffix_of_max
l1
l2
k
).
by
destruct
(
max_suffix_of
l1
l2
)
as
[[]?]
;
simplify_equality
.
Qed
.
Lemma
max_suffix_of_max_snoc
(
l1
l2
:
list
A
)
k1
k2
k3
x1
x2
:
max_suffix_of
l1
l2
=
(
k1
++
[
x1
],
k2
++
[
x2
],
k3
)
→
x1
≠
x2
.
Proof
.
intros
Hl
?.
subst
.
destruct
(
suffix_of_cons_not
x2
k3
).
eapply
max_suffix_of_max_alt
;
eauto
.
*
rewrite
(
max_suffix_of_fst_alt
_
_
_
_
_
Hl
).
by
apply
(
suffix_of_app
[
x2
]),
suffix_of_app_r
.
*
rewrite
(
max_suffix_of_snd_alt
_
_
_
_
_
Hl
).
by
apply
(
suffix_of_app
[
x2
]),
suffix_of_app_r
.
Qed
.
End
max_suffix_of
.
End
prefix_postfix
.
(** The [simplify_suffix_of] tactic removes [suffix_of] hypotheses that are
...
...
@@ -1455,8 +1661,13 @@ Section list_fmap.
Qed
.
Lemma
fmap_app
l1
l2
:
f
<$>
l1
++
l2
=
(
f
<$>
l1
)
++
(
f
<$>
l2
).
Proof
.
induction
l1
;
simpl
;
by
f_equal
.
Qed
.
Lemma
fmap_nil_inv
k
:
f
<$>
k
=
[]
→
k
=
[].
Proof
.
by
destruct
k
.
Qed
.
Lemma
fmap_cons_inv
y
l
k
:
f
<$>
l
=
y
::
k
→
∃
x
l'
,
y
=
f
x
∧
l
=
x
::
l'
.
f
<$>
l
=
y
::
k
→
∃
x
l'
,
y
=
f
x
∧
k
=
f
<$>
l'
∧
l
=
x
::
l'
.
Proof
.
intros
.
destruct
l
;
simpl
;
simplify_equality
;
eauto
.
Qed
.
Lemma
fmap_app_inv
l
k1
k2
:
f
<$>
l
=
k1
++
k2
→
∃
l1
l2
,
...
...
@@ -1610,7 +1821,7 @@ Section list_bind.
(
l1
++
l2
)
≫
=
f
=
(
l1
≫
=
f
)
++
(
l2
≫
=
f
).
Proof
.
induction
l1
;
simpl
;
[
done
|].