Skip to content

Commit b940ad5

Browse files
committed
Typos, rephrasings and more explanations
1 parent e846ca9 commit b940ad5

File tree

1 file changed

+104
-56
lines changed

1 file changed

+104
-56
lines changed

src/Tutorial_Equations_indexed.v

+104-56
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ From Equations Require Import Equations.
4848
Indexed inductive types are particular kind of inductive definitions
4949
that consist in defining not one single inductive type but a family
5050
of linked inductive types.
51-
The most well-known example of indexed inductive types are vectors.
51+
On of the most well-known examples of indexed inductive types are vectors.
5252
Given a fixed parameter [A : Type], vectors define a familly of inductive
5353
types [vec A n : Type] indexed by natural numbers [n : nat] representing
5454
the lengths of the vectors.
55-
Vectors have two constructor.
55+
The Vector type has two constructors.
5656
The first constructor [vnil : vec A 0] represent the empty vector,
5757
logically of size [0].
5858
Given an element [a:A] and a vector [v : vec A n] of size [n], the
@@ -73,17 +73,20 @@ Arguments vcons {_} _ _ _.
7373
For instance, in the definition of vectors the type [A] is a parameter
7474
as it is constant in all the constructors, but [n:nat] is an index as
7575
[vcons] relates two different types of the family, [vec A n] and [vec A (S n)].
76+
Indices always appear after the [:] in an inductive type declaration.
7677
7778
Reasoning about indexed inductive types like vectors is a bit more
7879
involved than for basic inductive types like lists as the indices can
7980
matter.
8081
Noticeably pattern matching on constructors of indexed inductive types
81-
like [vec n A] may particularise the indices.
82+
like [vec A n] may particularise the indices.
8283
For instance, matching a vector [v : vec A n] to [vnil] forces the
83-
value [n] to be [0] and to [vcons] to be of the form [S m] for some integer [m].
84+
value [n] to be [0] while for [vcons] if forces [n] to be of the form
85+
[S m] for some integer [m].
8486
Consequently, when writing a function on an indexed inductive type,
85-
we must also specify the form of the indices when pattern matching.
86-
87+
pattern-matching on the inductive type has an effect on other arguments
88+
of the function, specializing them.
89+
8790
For instance, consider the definition of [vmap] and [vapp] :
8891
*)
8992

@@ -93,10 +96,12 @@ vmap f _ (vcons a n v) := vcons (f a) n (vmap f n v).
9396

9497
Print vmap.
9598

96-
Equations vapp {A} (n : nat) (v : vec A n) (m : nat) (v' : vec A m) : vec A (n+m) :=
99+
Equations vapp {A} (na : nat) (v : vec A na) (m : nat) (v' : vec A m) : vec A (na+m) :=
97100
vapp 0 vnil m v' := v';
98101
vapp (S n) (vcons a n v) m v' := vcons a (n+m) (vapp n v m v').
99102

103+
(* Here the only two possibly well-typed patterns when considering the [vnil] and [vcons]
104+
constructors are respectively with [na = 0] and [na = S n] for some fresh [n] variable. *)
100105

101106
(** Reasoning on indexed inductive is not very different from reasoning
102107
on regular inductive types except that we have to account for indices,
@@ -144,7 +149,7 @@ Proof.
144149
cbn.
145150
(* We can now simplify *)
146151
simp vmap vapp. now rewrite H.
147-
Abort.
152+
Qed.
148153

149154
(** This is not a limitation of [Equations] itself. It is due to how the
150155
[rewrite] tactic behind [simp] unifies terms.
@@ -179,7 +184,7 @@ vapp' (vcons a v) v' := vcons a (vapp' v v').
179184
As an example, let's reprove [vmap_vapp] :
180185
*)
181186

182-
Definition vmap_vapp {A B n m }(f : A -> B) (v : vec A n) (v' : vec A m) :
187+
Definition vmap_vapp' {A B n m }(f : A -> B) (v : vec A n) (v' : vec A m) :
183188
vmap' f (vapp' v v') = vapp' (vmap' f v) (vmap' f v').
184189
Proof.
185190
funelim (vmap' f v).
@@ -195,6 +200,20 @@ Proof.
195200
simp vmap' vapp'. f_equal. apply H.
196201
Abort.
197202

203+
(** An alternative is to change the way [rewrite] looks for matching subterms
204+
in the goal, using the keyed unification strategy. With this setting, [rewrite (e : t = u)]
205+
looks for a syntactic match for the head of [t] in the goal but allows full
206+
conversion between arguments of [t] and the arguments of the matched application
207+
in the goal. This makes [simp] work up-to conversion of the indices.
208+
We can then directly call [congruence] to solve the induction case. *)
209+
210+
#[local] Set Keyed Unification.
211+
212+
Definition vmap_vapp_simp {A B n m }(f : A -> B) (v : vec A n) (v' : vec A m) :
213+
vmap' f (vapp' v v') = vapp' (vmap' f v) (vmap' f v').
214+
Proof.
215+
funelim (vmap' f v); simp vmap' vapp'; [reflexivity|congruence].
216+
Qed.
198217

199218
(** ** 2. Advanced Dependent Pattern Matching
200219
@@ -204,8 +223,8 @@ Abort.
204223
can have advantages.
205224
Most noticeably, it can be used to exclude invalid cases automatically.
206225
For instance, consider the function tail that returns the last element.
207-
In the case of [list], the [tail] function had to return a term of type
208-
[option A] as were no insurance that the input would not be the empty list.
226+
In the case of [list], the [tail] function has to return a term of type
227+
[option A] as there is no guarantee that the input is not the empty list.
209228
This is not necessary for vectors as we can use the index to ensure
210229
there is at least one element by defining tail as a function of type
211230
[vec A (S n) -> vec A n].
@@ -229,11 +248,13 @@ vtail (vcons a v) := v.
229248
| |
230249
]]
231250
232-
it returns [a] added to the diagonal of vmap [vtail v'], that is
251+
it returns [a] added to the diagonal of [vmap vtail v'], that is
233252
[v'] where the first column has been forgotten.
234253
235-
Note, that in this case, pattern match on [n] needs to be added to help
236-
Coq see it is strictly decreasing.
254+
Note, that in this case, pattern matching on [n] needs to be added to help
255+
Coq see it is a strictly decreasing structurally recursive definition on the index.
256+
[vmap vtail v'] can otherwise not be recognized as a syntactic subterm of [v'].
257+
An alternative definition using well founded-recursion is presented below.
237258
*)
238259

239260
Equations diag {A n} (v : vec (vec A n) n) : vec A n :=
@@ -253,10 +274,10 @@ Proof.
253274
(* We start by induction, simplify and use the induction hypothesis *)
254275
funelim (diag v); simp vmap diag. 1: easy. rewrite H. f_equal.
255276
(* We simplify the goal by collapsing the different [vmap] using [vmap_comp],
256-
and notice the proof boils down to commutativity if [vtail] and [vmap] *)
277+
and notice the proof boils down to commutativity of [vtail] and [vmap] *)
257278
rewrite ! vmap_comp. f_equal. apply vmap_cong.
258279
(* There is left to prove by function elimination on [vtail] or [vmap] *)
259-
intro v2. funelim (vtail v2). simp vmap vtail. reflexivity.
280+
intro v2. clear -v2. funelim (vtail v2). simp vmap vtail. reflexivity.
260281
Qed.
261282

262283

@@ -266,75 +287,86 @@ Qed.
266287
no-confusion properties to deduce which cases are impossible, enabling to
267288
write concise code where all uninteresting cases are handled automatically.
268289
269-
No confusion properties basically embodies both discrimination and injectivity
290+
No-confusion properties basically embodies both discrimination and injectivity
270291
of constructors: they assert which equations are impossible because the head
271-
constructors do not match, and if they do, simplify the equations.
292+
constructors do not match, or if they do match, simplify to equations between the
293+
constructor arguments.
272294
273-
The cases above relies on the no-confusion property for [nat], that given
295+
The cases above rely on the no-confusion property for [nat], that given
274296
[n], [m] eturns [True] if [n] and [m] are both [0], [n = m] if they are both
275297
of the form [S n], [S m], and [False] otherwise.
276298
277-
[Equations] provides a [Derive] command to generate them automatically.
299+
[Equations] provides a [Derive] command to generate this notion automatically
300+
for each inductive type.
278301
For instance, for [nat], it suffices to write:
279302
*)
280303

281304
Derive NoConfusion for nat.
282-
Check NoConfusion_nat.
305+
Print NoConfusion_nat.
283306

284-
(** You may have noticed that we have derive the no confusion property for [nat]
307+
(** You may have noticed that we have derived the no-confusion property for [nat]
285308
after defining [tail] and [diag], even though it is supposed to be necessary.
286309
This is because it is already defined for [nat] by default, so there was
287310
actually no need to do derive it in this particular case.
288311
289312
[nat] is a very simple inductive type.
290-
In the general case, for index inductive types, they are two kind of no-confusion
313+
In the general case, for indexed inductive types, there are two kind of no-confusion
291314
properties that can be derived by [Equations]:
292-
- The [NoConfusion] property that enable to distinguish object with different indices.
293-
It takes as argument objects in the total space {n : nat & vec A n}:
315+
- The [NoConfusion] property that enables to distinguish object with different indices.
316+
It takes as argument objects in the total space {n : nat & vec A n} and it is used
317+
to solve general equations between objects in potentially different instances of the
318+
inductive family:
294319
*)
295320
Derive NoConfusion for vec.
296321
Check NoConfusion_vec.
297322

298323
(**
299-
- The [NoConfusionHom] property that enables to disinguish objects with the
300-
same indices, which is useful for simplifying equations:
324+
- The [NoConfusionHom] property that enables to distinguish objects with the
325+
same indices (i.e., in the same instance of the inductive family), which
326+
is useful for simplifying homogeneous equations:
301327
*)
302328

303329
Derive NoConfusionHom for vec.
304-
Check NoConfusionHom_vec.
330+
Print NoConfusionHom_vec.
305331

306-
(** Though, the [NonConfusionHom] property is derivable for most index inductive types,
307-
it is not the case that is is derivable for all index inductive types.
308-
It only is when equality of constructors can be reduced to equality of forced
309-
argument, that is ???
332+
(** Though, the [NoConfusionHom] property is derivable for many indexed inductive types,
333+
it is not the case that is derivable for all indexed inductive types.
334+
It is derivable only when equality of constructors can be reduced to equality
335+
of the non-forced constructor arguments. For example on vectors, this
336+
corresponds to the fact that
337+
[vcons a n v = vcons a' n v' :> vec A (S n) <-> a = a' /\ v = v' :> vec A n].
310338
311339
If it is not possible to derive it, then [Equations] may need the indices to
312-
satify Uniqueness of Identity Proof, asserting that all proofs are equal, i.e.
313-
[UIP : forall (A : Type) (a b : A) (p q : a = b), p = q], to be able to
340+
satify Uniqueness of Identity Proofs, asserting that all equality proofs are
341+
equal, i.e. [UIP : forall (A : Type) (a b : A) (p q : a = b), p = q], to be able to
314342
elaborate the definition to a Coq term.
315343
316-
UIP holds for some types like [nat], but in the general case, this is an axiom.
317-
It is compatible with Coq and classical logical but inconsistent
318-
with univalence, so you may not want to admit it globally in your development.
344+
UIP holds for types like [nat] where equality is decidable, but it is not provable
345+
for all types. In particular, it is not provable for [Type] itself.
346+
It can be assumed as an axiom, but be mindful that while this is consistent with Coq's
347+
vanilla theory and classical logic axioms, it is inconsistent with univalence, so you
348+
may not want to admit it globally in your development. Also, as for any axiom,
349+
it will computation stuck: [Equations] definitions relying on it will only be
350+
simplifiable using [simp] but no longer compute using e.g. [Eval compute].
351+
319352
Consequently, [Equations] offers both options: you can declare it only for the types
320-
for which you can prove it or need it, or or assume it globally:
353+
for which you can prove it or need it, or assume it globally:
321354
*)
322355

323-
(* Assuming you can prove it *)
324-
Axiom uip_nat : UIP nat.
356+
(** Assuming you can prove it, from e.g. decidability of equality *)
357+
Definition uip_nat : UIP nat := eqdec_uip nat_EqDec.
325358
Local Existing Instance uip_nat.
326359

360+
(** Dangerous, incompatible with univalence, and results in stuck computations. *)
327361
Axiom uipa : forall A, UIP A.
328362
Local Existing Instance uipa.
329363

330-
331-
332364
(** *** 2.3 The Tactic Depelim *)
333365

334366
(** [Equations] provide a tactic [depelim] to recursively simplify and invert
335367
equations and simplify the goals, which is based on the [NoConfusion]
336368
principles and [Equations] simplification engine.
337-
When index inductive types are involved, it often provides a better simplification
369+
When indexed inductive types are involved, it often provides a better simplification
338370
tactic than the default [inversion] tactic.
339371
*)
340372

@@ -353,11 +385,11 @@ Qed.
353385
Goal forall (x : vec nat 2), (vcons 0 x = vcons 1 x) -> False.
354386
intros x H. depelim H.
355387
Qed.
356-
388+
End Foo.
357389

358390
(** ** 3. Unifying Indices and Inaccessible Patterns
359391
360-
A particularity of indexed inductive type is that during pattern-matching
392+
A particularity of indexed inductive types is that during pattern-matching
361393
indices may be particularised to values like variables or terms of
362394
the form [(f (...))], where [f] is not a constructor of an inductive type
363395
like [O] or [S].
@@ -366,8 +398,8 @@ Qed.
366398
that is _parameterized_ by a value [x] of type [A] and _indexed_
367399
by another value of type [A].
368400
Its single constructor states that equality is reflexive, so the only way
369-
to build an object of [eq x y] is if [x] is definitionally equal to the
370-
variable [y].
401+
to build an object of [eq x y] (in the empty context) is if [x] is
402+
definitionally equal to the term [y].
371403
372404
[[
373405
Inductive eq (A : Type) (x : A) : A -> Prop :=
@@ -376,22 +408,23 @@ Qed.
376408
377409
Pattern-matching on the equality then unifies the index [y] with the
378410
parameter [x], that is to a variable.
379-
Consequently, we have determined the _value_ of the pattern [y], and it is
380-
no longer a candidate for refinement with available constructors like
411+
Consequently, we have determined the _value_ of the pattern [y] to be [x],
412+
and it is no longer a candidate for refinement with available constructors like
381413
[0] or [S n].
382414
Such a pattern is said to be "inaccessible", and needs to be indicated
383-
by writing [?(t)] to tell Equations not to refine it.
415+
by writing [?(t)] to tell Equations not to refine it but rather check its
416+
inferrability.
384417
385418
As an example, to prove the symmetry of equality we pattern
386419
match on an equality [H : x = y], which unify [y] the variable [x]
387420
that we indicate by writing [eq_sym x ?(x) eq_refl].
388-
The goal now being [x = x], it now holds by [eq_refl].
421+
The goal now being [x = x], it holds by [eq_refl].
389422
*)
390423

391424
Equations eq_sym {A} (x y : A) (H : x = y) : y = x :=
392425
eq_sym x ?(x) eq_refl := eq_refl.
393426

394-
(** In practice, when the values determined are variable as in [eq_sym],
427+
(** In practice, when the values determined are variables as in [eq_sym],
395428
the inaccessibility annotation is optional and we can simply write [x]
396429
or a wild card [_] rather than [?(x)].
397430
*)
@@ -413,9 +446,8 @@ Inductive Imf {A B} (f : A -> B) : B -> Type
413446
(** Pattern-matching on [im : Imf f t] particularise [t] to be of the form
414447
[f a] for some [a].
415448
As [f] is not a constructor, [f a] is inaccessible and we need to write
416-
as [?(f a)] in the pattern matching to prevent [Equations] to refine [f]
417-
with available constructors.
418-
In this case, it is essential as [f a] is not a variable.
449+
as [?(f a)] in the pattern matching to prevent [Equations] to try to
450+
interpret [f] as a constructor.
419451
As an example, we can write a function returning the [a] associated
420452
to an object in the image :
421453
*)
@@ -426,7 +458,7 @@ inv f ?(f s) (imf f s) := s.
426458
(** Be careful that if you forget to mark inaccessible patterns, then [Equations]
427459
will try to match on the patterns, creating potentially pointless branches.
428460
It is fine in theory as the definition obtained will be logically equivalent
429-
provided elaboration succededs, but annoying if you want to extract the code as the definition will be more involved.
461+
provided elaboration succeeded, but annoying if you want to extract the code as the definition will be more involved.
430462
431463
For instance, if we define [vmap''] by matching on [n] without marking the
432464
pattern associated to [n] as inaccessible, we can see at extraction that [Equations]
@@ -440,3 +472,19 @@ vmap'' f (S n) (vcons a v) := vcons (f a) (vmap'' f n v).
440472

441473
Extraction vmap.
442474
Extraction vmap''.
475+
476+
(** Using inaccessible patterns hence allows to separate explicitely the subjects of
477+
pattern-matchings and the inferred indices in definitions. The following alternative
478+
definition of the square matrix diagonal pattern-matches only on the [vec] argument,
479+
but uses well-founded recursion on the index [n] to justify termination, as
480+
[vmap vtail v'] is not a subterm of [v']. *)
481+
482+
Equations diag_wf {A n} (v : vec (vec A n) n) : vec A n by wf n :=
483+
diag_wf (n:=?(O)) vnil := vnil ;
484+
diag_wf (n:=?(S _)) (vcons (vcons a v) v') := vcons a (diag_wf (vmap vtail v')).
485+
486+
(* Again, one can observe the extractions of the two diagonal definitions to see
487+
that [diag_wf] is more efficient, not needing to pattern-match on the indices first. *)
488+
489+
Extraction diag.
490+
Extraction diag_wf.

0 commit comments

Comments
 (0)