-
Notifications
You must be signed in to change notification settings - Fork 19
/
CoqWS_demo.v
246 lines (180 loc) · 6.35 KB
/
CoqWS_demo.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
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
(* Accompanying material to Coq workshop presentation *)
From Coq Require Import ssreflect ssrfun ZArith.
From HB Require Import structures.
Set Warnings "-redundant-canonical-projection".
(* ****************************************************** *)
(* ******** 1. Building the hierarchy ********** *)
(* ****************************************************** *)
(* ********************************************************
The set of axioms that turn a naked type A
into a Commutative Monoid.
This would be the puzzle piece.
*)
HB.mixin (* an HB command *)
Record CMonoid_of_Type A := { (* and its argument *)
zero : A;
add : A -> A -> A;
addrA : associative add;
addrC : commutative add;
add0r : left_id zero add;
}.
(* ********************************************************
The structure of Commutative Monoids
This would be the blue dotted box
Note: { A of ... } is just a notation for a sigma type
*)
HB.structure
Definition CMonoid := { A of CMonoid_of_Type A }.
(* ********************************************************
Monoid playground
*)
(* Operations are now available *)
Check add.
(* Axioms are also there *)
Check addrC.
(* We can develop the abstract theory of CMonoid *)
Notation "0" := zero.
Infix "+" := add.
Lemma silly :
forall (M : CMonoid.type) (x : M), x + 0 = 0 + x.
Proof. by move=> M x; rewrite addrC. Qed.
(* ********************************************************
The puzzle piece on the right and the AbelianGrp str.
Note: it requires A to be a monoid, indeed the property
talk about both add and opp
*)
HB.mixin
Record AbelianGrp_of_CMonoid A of CMonoid A := {
opp : A -> A;
addNr : left_inverse zero opp add;
}.
HB.structure
Definition AbelianGrp := { A of AbelianGrp_of_CMonoid A }.
Notation "- x" := (opp x).
Notation "x - y" := (add x (opp y)).
(* Quick check that - and + and 0 are compatible *)
Check forall x y, x - (y + 0) = x.
(* ********************************************************
The puzzle piece on the left and the SemiRing str.
*)
HB.mixin
Record SemiRing_of_CMonoid A of CMonoid A := {
one : A;
mul : A -> A -> A;
mulrA : associative mul;
mul1r : left_id one mul;
mulr1 : right_id one mul;
mulrDl : left_distributive mul add;
mulrDr : right_distributive mul add;
mul0r : left_zero zero mul;
mulr0 : right_zero zero mul;
}.
HB.structure
Definition SemiRing := { A of SemiRing_of_CMonoid A & }.
Notation "1" := one.
Infix "*" := mul.
(* Quick check that + and 1 and * are compatible *)
Check forall x y, 1 + x = y * x.
(* ********************************************************
Can I mix * and - in the same expression?
*)
Fail Check forall x y, 1 * x = y - x.
(* ********************************************************
The missing structure, no puzzle piece is missing
*)
HB.structure
Definition Ring := { A of SemiRing A & AbelianGrp A }.
Check forall (R : Ring.type) (x y : R), 1 * x = y - x.
Check forall x y, 1 * x = y - x.
(* ****************************************************** *)
(* ******** 2. Declaring instances ******** *)
(* ****************************************************** *)
(* ******************************************************
Inhabiting the puzzle pieces with Z
*)
Module Z_instances.
HB.instance
Definition Z_CMonoid := CMonoid_of_Type.Build Z
0%Z Z.add Z.add_assoc Z.add_comm Z.add_0_l.
HB.instance
Definition Z_AbelianGrp := AbelianGrp_of_CMonoid.Build Z
Z.opp Z.add_opp_diag_l.
HB.instance
Definition Z_SemiRing := SemiRing_of_CMonoid.Build Z
1%Z Z.mul Z.mul_assoc Z.mul_1_l Z.mul_1_r
Z.mul_add_distr_r Z.mul_add_distr_l Z.mul_0_l Z.mul_0_r.
(* Now Z is recognized as a Ring *)
Check forall x : Z, x * - (1 + x) = 0 + 1.
End Z_instances.
(* ****************************************************** *)
(* ********** 3. Being nice with users ******** *)
(* ****************************************************** *)
(* ********************************************************
Crafting special builders
We provide an API to build a ring directly.
A factory is a ''virtual'' puzzle piece that can be
''compiled'' to other puzzle pieces.
*)
HB.factory
Record Ring_of_Type A := {
zero : A;
add : A -> A -> A;
opp : A -> A;
one : A;
mul : A -> A -> A;
addrA : associative add;
(*addrC : commutative add; *)
add0r : left_id zero add;
addr0 : right_id zero add; (* new *)
addNr : left_inverse zero opp add;
addrN : right_inverse zero opp add; (* new *)
mulrA : associative mul;
mul1r : left_id one mul;
mulr1 : right_id one mul;
mulrDl : left_distributive mul add;
mulrDr : right_distributive mul add;
mul0r : left_zero zero mul;
mulr0 : right_zero zero mul;
}.
(* The ''compilation'' of a factory *)
HB.builders
Context A of Ring_of_Type A.
(* We are in a Context with a type A that with operations
and properties, but wich is not yet known to be a Ring *)
Check add.
Local Infix "+" := add.
(* We prove commutativity as per Hankel 1867 *)
Lemma addrC : commutative add.
Proof.
have innerC (a b : A) : a + b + (a + b) = a + a + (b + b).
by rewrite -[a + b]mul1r -mulrDl mulrDr !mulrDl !mul1r.
have addKl (a b c : A) : a + b = a + c -> b = c.
apply: can_inj (add a) (add (opp a)) _ _ _.
by move=> x; rewrite addrA addNr add0r.
have addKr (a b c : A) : b + a = c + a -> b = c.
apply: can_inj (add ^~ a) (add ^~ (opp a)) _ _ _.
by move=> x; rewrite /= -addrA addrN addr0.
move=> x y; apply: addKl (x) _ _ _; apply: addKr (y) _ _ _.
by rewrite -!addrA [in RHS]addrA innerC !addrA.
Qed.
HB.instance
Definition A_CMonoid := CMonoid_of_Type.Build A
zero add addrA addrC add0r.
HB.instance
Definition A_AbelianGrp := AbelianGrp_of_CMonoid.Build A
opp addNr.
HB.instance
Definition A_SemiRing := SemiRing_of_CMonoid.Build A
one mul mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0.
HB.end.
(* Let's use the new builder *)
Module Z_instances_again.
HB.instance
Definition Z_Ring := Ring_of_Type.Build Z
0%Z Z.add Z.opp 1%Z Z.mul
Z.add_assoc (* Z.add_comm *) Z.add_0_l Z.add_0_r
Z.add_opp_diag_l Z.add_opp_diag_r
Z.mul_assoc Z.mul_1_l Z.mul_1_r
Z.mul_add_distr_r Z.mul_add_distr_l Z.mul_0_l Z.mul_0_r.
Check forall x : Z, x * - (1 + x) = 0 + 1.
End Z_instances_again.