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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
Parameter Inline recursion : forall A : Set, A -> (N -> A -> A) -> N -> A.
Implicit Arguments recursion [A].
(* Suppose the codomain A has a setoid equality relation EA. If A is a
function space C -> D, it makes sense to consider extensional
functional equality as EA. Indeed, suppose, for example, that we say
[Definition g (x : N) : C -> D := (recursion ... x ...)]. We would
like to show that the function g of two arguments is well-defined.
This requirement is the same as the requirement that the functions of
one argument (g x) and (g x') are extensionally equal whenever x ==
x', i.e.,
forall x x' : N, x == x' -> eq_fun (g x) (g x'),
which is the same as
forall x x' : N, x == x' -> forall y y' : C, EC y y' -> ED (g x y) (g x' y')
where EC and ED are setoid equalities on C and D, respectively.
Now, if we consider EA to be extensional equality on the function
space, we cannot require that EA is reflexive. Indeed, reflexivity of
EA:
forall f : C -> D, eq_fun f f
or
forall f : C -> D, forall x x', EC x x' -> ED (f x) (f x')
means that every function f ; C -> D is well-defined, which is in
general false. We can expect that EA is symmetric and transitive,
i.e., that EA is a partial equivalence relation (PER). However, there
seems to be no need to require this in the following axioms.
When we defined a function by recursion, the arguments of this
function may occur in the recursion's base case a, the counter x, or
the step function f. For example, in the following definition:
Definition plus (x y : N) := recursion y (fun _ p => S p) x.
one argument becomes the base case and the other becomes the counter.
In the definitions of times:
Definition times (x y : N) := recursion 0 (fun x p => plus y p) x.
the argument y occurs in the step function. Thus it makes sense to
formulate an axiom saying that (recursion a f x) is equal to
(recursion a' f' x') whenever (EA a a'), x == x', and eq_fun2 f f'. We
need to vary all three arguments; for example, claiming that
(recursion a f x) equals (recursion a' f x') with the same f whenever
(EA a a') and x == x' is not enough to prove well-defidedness of
multiplication defined above.
This leads to the axioms given below. There is a question if it is
possible to formulate simpler axioms that would imply this statement
for any implementation. Indeed, the proof seems to have to proceed by
straighforward induction on x. The difficulty is that we cannot prove
(EA (recursion a f x) (recursion a' f' x')) using the induction axioms
above because recursion is not declared to be a setoid morphism:
that's what we are proving! Therefore, this has to be proved by
induction inside each particular implementation. *)
Axiom recursion_wd : forall (A : Set) (EA : relation A),
forall a a' : A, EA a a' ->
forall f f' : N -> A -> A, eq_fun2 E EA EA f f' ->
forall x x' : N, x == x' ->
EA (recursion a f x) (recursion a' f' x').
(* Can we instead declare recursion as a morphism? It does not seem
so. For this, we need to register the relation EA, and for this we
need to declare it as a variable in a section. But information about
morhisms is lost when sections are closed. *)
(* When the function recursion is polymorphic on the codomain A, there
seems no other option than to return the given base case a when the
counter is 0. Therefore, we can formulate the following axioms with
Leibniz equality. *)
Axiom recursion_0 :
forall (A : Set) (a : A) (f : N -> A -> A), recursion a f 0 = a.
Axiom recursion_succ :
forall (A : Set) (EA : relation A) (a : A) (f : N -> A -> A),
EA a a -> fun2_wd E EA EA f ->
forall n : N, EA (recursion a f (S n)) (f n (recursion a f n)).
(* It may be possible to formulate recursion_0 and recursion_succ as follows:
Axiom recursion_0 :
forall (a : A) (f : N -> A -> A),
EA a a -> forall x : N, x == 0 -> EA (recursion a f x) a.
Axiom recursion_succ :
forall (a : A) (f : N -> A -> A),
EA a a -> fun2_wd E EA EA f ->
forall n m : N, n == S m -> EA (recursion a f n) (f m (recursion a f m)).
Then it is possible to prove recursion_wd (see IotherInd.v). This
raises some questions:
(1) Can the axioms recursion_wd, recursion_0 and recursion_succ (both
variants) proved for all reasonable implementations?
(2) Can these axioms be proved without assuming that EA is symmetric
and transitive? In OtherInd.v, recursion_wd can be proved from
recursion_0 and recursion_succ by assuming symmetry and transitivity.
(2) Which variant requires proving less for each implementation? Can
it be that proving all three axioms about recursion has some common
parts which have to be repeated? *)
Implicit Arguments recursion_wd [A].
Implicit Arguments recursion_0 [A].
Implicit Arguments recursion_succ [A].
Definition if_zero (A : Set) (a b : A) (n : N) : A :=
recursion a (fun _ _ => b) n.
Add Morphism if_zero with signature LE_succet ==> LE_succet ==> E ==> LE_succet as if_zero_wd.
Proof.
unfold LE_succet.
intros; unfold if_zero; now apply recursion_wd with (EA := (@eq A));
[| unfold eq_fun2; now intros |].
Qed.
Theorem if_zero_0 : forall (A : Set) (a b : A), if_zero A a b 0 = a.
Proof.
unfold if_zero; intros; now rewrite recursion_0.
Qed.
Theorem if_zero_succ : forall (A : Set) (a b : A) (n : N), if_zero A a b (S n) = b.
Proof.
intros; unfold if_zero.
now rewrite (recursion_succ (@eq A)); [| | unfold fun2_wd; now intros].
Qed.
Implicit Arguments if_zero [A].
(* To prove this statement, we need to provably different terms,
e.g., true and false *)
Theorem succ_0 : forall n, ~ S n == 0.
Proof.
intros n H.
assert (true = false); [| discriminate].
replace true with (if_zero false true (S n)) by apply if_zero_succ.
pattern false at 2; replace false with (if_zero false true 0) by apply if_zero_0.
change (LE_succet bool (if_zero false true (S n)) (if_zero false true 0)).
rewrite H. unfold LE_succet. reflexivity.
Qed.
Theorem succ_inj : forall m n, S m == S n -> m == n.
Proof.
intros m n H.
setoid_replace m with (A (S m)) by (symmetry; apply pred_succ).
setoid_replace n with (A (S n)) by (symmetry; apply pred_succ).
now apply pred_wd.
Qed.
(* The following section is devoted to defining a function that, given
two numbers whose some equals 1, decides which number equals 1. The
main property of the function is also proved .*)
(* First prove a theorem with ordinary disjunction *)
Theorem plus_eq_1 :
forall m n : N, m + n == 1 -> (m == 0 /\ n == 1) \/ (m == 1 /\ n == 0).
induct m.
intros n H; rewrite plus_0_l in H; left; now split.
intros n IH m H; rewrite plus_succ_l in H; apply succ_inj in H;
apply plus_eq_0 in H; destruct H as [H1 H2];
now right; split; [apply succ_wd |].
Qed.
Definition plus_eq_1_dec (m n : N) : bool := recursion true (fun _ _ => false) m.
Theorem plus_eq_1_dec_step_wd : fun2_wd E eq_bool eq_bool (fun _ _ => false).
Proof.
unfold fun2_wd; intros. unfold eq_bool. reflexivity.
Qed.
Add Morphism plus_eq_1_dec with signature E ==> E ==> eq_bool as plus_eq_1_dec_wd.
Proof.
unfold fun2_wd, plus_eq_1_dec.
intros x x' Exx' y y' Eyy'.
apply recursion_wd with (EA := eq_bool).
unfold eq_bool; reflexivity.
unfold eq_fun2; unfold eq_bool; reflexivity.
assumption.
Qed.
Theorem plus_eq_1_dec_0 : forall n : N, plus_eq_1_dec 0 n = true.
Proof.
intro n. unfold plus_eq_1_dec.
now apply recursion_0.
Qed.
Theorem plus_eq_1_dec_succ : forall m n : N, plus_eq_1_dec (S n) m = false.
Proof.
intros n m. unfold plus_eq_1_dec.
now rewrite (recursion_succ eq_bool);
[| unfold eq_bool | apply plus_eq_1_dec_step_wd].
Qed.
Theorem plus_eq_1_dec_correct :
forall m n : N, m + n == 1 ->
(plus_eq_1_dec m n = true -> m == 0 /\ n == 1) /\
(plus_eq_1_dec m n = false -> m == 1 /\ n == 0).
Proof.
intros m n; induct m.
intro H. rewrite plus_0_l in H.
rewrite plus_eq_1_dec_0.
split; [intros; now split | intro H1; discriminate H1].
intros m _ H. rewrite plus_eq_1_dec_succ.
split; [intro H1; discriminate | intros _ ].
rewrite plus_succ_l in H. apply succ_inj in H.
apply plus_eq_0 in H; split; [apply succ_wd | ]; tauto.
Qed.
Definition times_eq_0_dec (n m : N) : bool :=
recursion true (fun _ _ => recursion false (fun _ _ => false) m) n.
Lemma times_eq_0_dec_wd_step :
forall y y', y == y' ->
eq_bool (recursion false (fun _ _ => false) y)
(recursion false (fun _ _ => false) y').
Proof.
intros y y' Eyy'.
apply recursion_wd with (EA := eq_bool).
now unfold eq_bool.
unfold eq_fun2. intros. now unfold eq_bool.
assumption.
Qed.
Add Morphism times_eq_0_dec with signature E ==> E ==> eq_bool
as times_eq_0_dec_wd.
unfold fun2_wd, times_eq_0_dec.
intros x x' Exx' y y' Eyy'.
apply recursion_wd with (EA := eq_bool).
now unfold eq_bool.
unfold eq_fun2; intros. now apply times_eq_0_dec_wd_step.
assumption.
Qed.
Theorem times_eq_0_dec_correct :
forall n m, n * m == 0 ->
(times_eq_0_dec n m = true -> n == 0) /\
(times_eq_0_dec n m = false -> m == 0).
Proof.
nondep_induct n; nondep_induct m; unfold times_eq_0_dec.
rewrite recursion_0; split; now intros.
intro n; rewrite recursion_0; split; now intros.
intro; rewrite recursion_0; rewrite (recursion_succ eq_bool);
[split; now intros | now unfold eq_bool | unfold fun2_wd; unfold eq_bool; now intros].
intro m; rewrite (recursion_succ eq_bool).
rewrite times_succ_l. rewrite plus_succ_r. intro H; now apply succ_0 in H.
now unfold eq_bool.
unfold fun2_wd; intros; now unfold eq_bool.
Qed.
|