forked from antalsz/hs-to-coq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathListUtils.v
197 lines (160 loc) · 5.4 KB
/
ListUtils.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
Require Import Coq.Program.Basics.
Require Import Coq.Lists.List.
Import ListNotations.
Open Scope program_scope.
Require Import Coq.ZArith.ZArith.
Require Data.Foldable.
Require Data.Monoid.
Require Import Proofs.Data.Foldable.
From Coq Require Import ssreflect ssrfun ssrbool.
Set Bullet Behavior "Strict Subproofs".
(***** null *****)
Definition null {A} (l : list A) : bool :=
match l with
| [] => true
| _ :: _ => false
end.
Theorem app_null {A} (xs ys : list A) :
null (xs ++ ys) = null xs && null ys.
Proof. case: xs => //=. Qed.
(***** all and any *****)
Fixpoint all {A} (p : A -> bool) (l : list A) : bool :=
match l with
| [] => true
| x :: xs => p x && all p xs
end.
Fixpoint any {A} (p : A -> bool) (l : list A) : bool :=
match l with
| [] => false
| x :: xs => p x || any p xs
end.
Theorem all_xpred0 {A} (l : list A) :
all xpred0 l = null l.
Proof. by case: l. Qed.
Theorem all_xpredT {A} (l : list A) :
all xpredT l.
Proof. by elim: l. Qed.
Theorem any_xpred0 {A} (l : list A) :
~~ any xpred0 l.
Proof. by elim: l. Qed.
Theorem any_xpredT {A} (l : list A) :
any xpredT l = ~~ null l.
Proof. by case: l. Qed.
Theorem all_app {A} (p : A -> bool) (l1 l2 : list A) :
all p (l1 ++ l2) = all p l1 && all p l2.
Proof. by elim: l1 => [|x1 l1 IH] //=; rewrite IH andbA. Qed.
Theorem any_app {A} (p : A -> bool) (l1 l2 : list A) :
any p (l1 ++ l2) = any p l1 || any p l2.
Proof. by elim: l1 => [|x1 l1 IH] //=; rewrite IH orbA. Qed.
Theorem all_ext {A} (p1 p2 : A -> bool) (l : list A) :
p1 =1 p2 ->
all p1 l = all p2 l.
Proof. by move=> ext; elim: l => [|x l IH] //=; rewrite ext IH. Qed.
Theorem any_ext {A} (p1 p2 : A -> bool) (l : list A) :
p1 =1 p2 ->
any p1 l = any p2 l.
Proof. by move=> ext; elim: l => [|x l IH] //=; rewrite ext IH. Qed.
Theorem allP {A} (p : A -> bool) (l : list A) :
reflect (Forall p l) (all p l).
Proof.
elim: l => [|x l IH] /=.
- by left.
- case p_x: (p x) => /=.
+ case: IH => [Forall_l | Exists_not_l].
* by left; constructor.
* by right; contradict Exists_not_l; inversion Exists_not_l.
+ by right; inversion 1; rewrite ->p_x in *.
Qed.
Theorem anyP {A} (p : A -> bool) (l : list A) :
reflect (Exists p l) (any p l).
Proof.
elim: l => [|x l IH] /=.
- right; inversion 1.
- case p_x: (p x) => /=.
+ by left; constructor.
+ case: IH => [Exists_l | Forall_not_l].
* by left; apply Exists_cons_tl.
* by right; contradict Forall_not_l; inversion Forall_not_l => //=; rewrite ->p_x in *.
Qed.
(***** filter *****)
Theorem filter_app {A} (p : A -> bool) (l1 l2 : list A) :
filter p (l1 ++ l2) = filter p l1 ++ filter p l2.
Proof.
elim: l1 => [|x1 l1 IH] //=.
case: (p x1) => //=.
by rewrite IH.
Qed.
Theorem filter_xpredT {A} (l : list A) :
filter xpredT l = l.
Proof. by elim: l => [| ? ? IH] //=; rewrite IH. Qed.
(***** fold_right *****)
Theorem fold_right_cons {A} (tail l : list A) :
fold_right cons tail l = l ++ tail.
Proof.
elim: l => [| x l IH] //=.
by rewrite IH.
Qed.
Corollary fold_right_cons_nil {A} (l : list A) :
fold_right cons [] l = l.
Proof. by rewrite fold_right_cons app_nil_r. Qed.
Theorem fold_right_map {A B C} (f : B -> C -> C) (z : C) (g : A -> B) (l : list A) :
fold_right f z (map g l) = fold_right (f ∘ g) z l.
Proof.
elim: l => [|x l IH] //=.
by rewrite IH.
Qed.
Theorem fold_right_fold_right {A} (f : A -> A -> A) (z : A) (l1 l2 : list A) :
associative f -> left_id z f ->
fold_right f (fold_right f z l2) l1 = f (fold_right f z l1) (fold_right f z l2).
Proof.
move=> f_assoc z_left_id.
elim: l1 => [|x1 l1 IH] //=.
by rewrite IH f_assoc.
Qed.
Theorem hs_coq_any_list {A} (p : A -> bool) (l : list A) :
Data.Foldable.any p l = any p l.
Proof.
rewrite /Data.Foldable.any
/Data.Foldable.foldMap /Foldable.Foldable__list /Foldable.foldMap__
/= /Data.Foldable.Foldable__list_foldMap
/Data.Foldable.Foldable__list_foldr /=
/Base.mempty /SemigroupInternal.Monoid__Any /Base.mempty__
/SemigroupInternal.Monoid__Any_mempty
/Base.op_z2218U__.
rewrite -(orbF (any p l)); move: false => b.
elim: l => [|x l IH] //=.
rewrite -orbA -IH /compose /=.
by case: (GHC.Base.foldr _ _ _); case: (p x).
Qed.
(***** partition *****)
Theorem partition_app {A} (p : A -> bool) (l r : list A) :
let: (t, f) := partition p (l ++ r) in
let: (lt, lf) := partition p l in
let: (rt, rf) := partition p r
in t = lt ++ rt /\ f = lf ++ rf.
Proof.
elim: l => [|x l IH] //=.
- by case: (partition p r).
- case: (partition p r) (partition p l) (partition p (l ++ r)) IH
=> [rt rf] [lt lf] [? ?] [-> ->].
by case: (p x).
Qed.
Corollary partition_app_1 {A} (p : A -> bool) (l r : list A) :
fst (partition p (l ++ r)) = fst (partition p l) ++ fst (partition p r).
Proof.
by move: (partition p (l ++ r)) (partition p l) (partition p r) (partition_app p l r)
=> [? ?] [? ?] [? ?] [-> ->].
Qed.
Corollary partition_app_2 {A} (p : A -> bool) (l r : list A) :
snd (partition p (l ++ r)) = snd (partition p l) ++ snd (partition p r).
Proof.
by move: (partition p (l ++ r)) (partition p l) (partition p r) (partition_app p l r)
=> [? ?] [? ?] [? ?] [-> ->].
Qed.
(***** Zlength *****)
Section Z.
Open Scope Z_scope.
Theorem Zlength_app {A} (l r : list A) :
Zlength (l ++ r) = Zlength l + Zlength r.
Proof. by rewrite Zlength_correct app_length Nat2Z.inj_add -!Zlength_correct. Qed.
End Z.