├── Auto.v
├── Basics.v
├── Equiv.v
├── Extraction.v
├── Hoare.v
├── Hoare2.v
├── HoareAsLogic.v
├── Imp.v
├── ImpCEvalFun.v
├── ImpParser.v
├── Induction.v
├── LibTactics.v
├── Lists.v
├── Logic.v
├── MoreCoq.v
├── MoreInd.v
├── MoreLogic.v
├── MoreStlc.v
├── Norm.v
├── PE.v
├── Poly.v
├── Postscript.v
├── Preface.v
├── ProofObjects.v
├── Prop.v
├── README.md
├── RecordSub.v
├── Records.v
├── References.v
├── Rel.v
├── SepLogic.v
├── SfLib.v
├── Smallstep.v
├── Stlc.v
├── StlcProp.v
├── Sub.v
├── Symbols.v
├── Typechecking.v
├── Types.v
├── UseAuto.v
└── UseTactics.v
/Auto.v:
--------------------------------------------------------------------------------
1 | (** * Auto: More Automation *)
2 |
3 | Require Export Imp.
4 |
5 | (** Up to now, we've continued to use a quite restricted set of
6 | Coq's tactic facilities. In this chapter, we'll learn more about
7 | two very powerful features of Coq's tactic language:
8 | proof search via the [auto] and [eauto] tactics, and
9 | automated forward reasoning via the [Ltac] hypothesis matching
10 | machinery. Using these features together with Ltac's scripting facilities
11 | will enable us to make our proofs startlingly short! Used properly,
12 | they can also make proofs more maintainable and robust in the face
13 | of incremental changes to underlying definitions.
14 |
15 | There's a third major source of automation we haven't
16 | fully studied yet, namely built-in decision procedures for specific
17 | kinds of problems: [omega] is one example, but there are others.
18 | This topic will be defered for a while longer.
19 |
20 | *)
21 |
22 | (** Our motivating example will be this proof, repeated with
23 | just a few small changes from [Imp]. We will try to simplify
24 | this proof in several stages. *)
25 |
26 | Ltac inv H := inversion H; subst; clear H.
27 |
28 | Theorem ceval_deterministic: forall c st st1 st2,
29 | c / st || st1 ->
30 | c / st || st2 ->
31 | st1 = st2.
32 | Proof.
33 | intros c st st1 st2 E1 E2;
34 | generalize dependent st2;
35 | ceval_cases (induction E1) Case;
36 | intros st2 E2; inv E2.
37 | Case "E_Skip". reflexivity.
38 | Case "E_Ass". reflexivity.
39 | Case "E_Seq".
40 | assert (st' = st'0) as EQ1.
41 | SCase "Proof of assertion". apply IHE1_1; assumption.
42 | subst st'0.
43 | apply IHE1_2. assumption.
44 | Case "E_IfTrue".
45 | SCase "b evaluates to true".
46 | apply IHE1. assumption.
47 | SCase "b evaluates to false (contradiction)".
48 | rewrite H in H5. inversion H5.
49 | Case "E_IfFalse".
50 | SCase "b evaluates to true (contradiction)".
51 | rewrite H in H5. inversion H5.
52 | SCase "b evaluates to false".
53 | apply IHE1. assumption.
54 | Case "E_WhileEnd".
55 | SCase "b evaluates to false".
56 | reflexivity.
57 | SCase "b evaluates to true (contradiction)".
58 | rewrite H in H2. inversion H2.
59 | Case "E_WhileLoop".
60 | SCase "b evaluates to false (contradiction)".
61 | rewrite H in H4. inversion H4.
62 | SCase "b evaluates to true".
63 | assert (st' = st'0) as EQ1.
64 | SSCase "Proof of assertion". apply IHE1_1; assumption.
65 | subst st'0.
66 | apply IHE1_2. assumption. Qed.
67 |
68 | (** * The [auto] and [eauto] tactics *)
69 |
70 | (** Thus far, we have (nearly) always written proof scripts that
71 | apply relevant hypothoses or lemmas by name. In particular, when
72 | a chain of hypothesis applications is needed, we have specified
73 | them explicitly. (The only exceptions introduced so far are using
74 | [assumption] to find a matching unqualified hypothesis
75 | or [(e)constructor] to find a matching constructor.) *)
76 |
77 |
78 | Example auto_example_1 : forall (P Q R: Prop), (P -> Q) -> (Q -> R) -> P -> R.
79 | Proof.
80 | intros P Q R H1 H2 H3.
81 | apply H2. apply H1. assumption.
82 | Qed.
83 |
84 | (** The [auto] tactic frees us from this drudgery by _searching_
85 | for a sequence of applications that will prove the goal *)
86 |
87 | Example auto_example_1' : forall (P Q R: Prop), (P -> Q) -> (Q -> R) -> P -> R.
88 | Proof.
89 | intros P Q R H1 H2 H3.
90 | auto.
91 | Qed.
92 |
93 | (** The [auto] tactic solves goals that are solvable by any combination of
94 | - [intros],
95 | - [apply] (with a local hypothesis, by default).
96 |
97 | The [eauto] tactic works just like [auto], except that it uses
98 | [eapply] instead of [apply]. *)
99 |
100 | (** Using [auto] is always "safe" in the sense that it will never fail
101 | and will never change the proof state: either it completely solves
102 | the current goal, or it does nothing.
103 | *)
104 |
105 | (** A more complicated example: *)
106 |
107 | Example auto_example_2 : forall P Q R S T U : Prop,
108 | (P -> Q) ->
109 | (P -> R) ->
110 | (T -> R) ->
111 | (S -> T -> U) ->
112 | ((P->Q) -> (P->S)) ->
113 | T ->
114 | P ->
115 | U.
116 | Proof. auto. Qed.
117 |
118 |
119 | (** Search can take an arbitrarily long time, so there are limits to
120 | how far [auto] will search by default *)
121 |
122 | Example auto_example_3 : forall (P Q R S T U: Prop),
123 | (P -> Q) -> (Q -> R) -> (R -> S) ->
124 | (S -> T) -> (T -> U) -> P -> U.
125 | Proof.
126 | auto. (* When it cannot solve the goal, does nothing! *)
127 | auto 6. (* Optional argument says how deep to search (default depth is 5) *)
128 | Qed.
129 |
130 |
131 | (** When searching for potential proofs of the current goal, [auto]
132 | and [eauto] consider the hypotheses in the current context
133 | together with a _hint database_ of other lemmas and constructors.
134 | Some of the lemmas and constructors we've already seen -- e.g.,
135 | [eq_refl], [conj], [or_introl], and [or_intror] -- are installed in this hint
136 | database by default. *)
137 |
138 | Example auto_example_4 : forall P Q R : Prop,
139 | Q ->
140 | (Q -> R) ->
141 | P \/ (Q /\ R).
142 | Proof.
143 | auto. Qed.
144 |
145 |
146 | (** If we want to see which facts [auto] is using, we can use [info_auto] instead. *)
147 |
148 | Example auto_example_5: 2 = 2.
149 | Proof.
150 | info_auto. (* subsumes reflexivity because eq_refl is in hint database *)
151 | Qed.
152 |
153 |
154 | (** We can extend the hint database just for the purposes of one
155 | application of [auto] or [eauto] by writing [auto using ...]. *)
156 |
157 | Lemma le_antisym : forall n m: nat, (n <= m /\ m <= n) -> n = m.
158 | Proof. intros. omega. Qed.
159 |
160 | Example auto_example_6 : forall n m p : nat,
161 | (n<= p -> (n <= m /\ m <= n)) ->
162 | n <= p ->
163 | n = m.
164 | Proof.
165 | intros.
166 | auto. (* does nothing: auto doesn't destruct hypotheses! *)
167 | auto using le_antisym.
168 | Qed.
169 |
170 |
171 | (** Of course, in any given development there will also be some of our
172 | own specific constructors and lemmas that are used very often in
173 | proofs. We can add these to the global hint database by writing
174 | Hint Resolve T.
175 | at the top level, where [T] is a top-level theorem or a
176 | constructor of an inductively defined proposition (i.e., anything
177 | whose type is an implication). As a shorthand, we can write
178 | Hint Constructors c.
179 | to tell Coq to do a [Hint Resolve] for _all_ of the constructors
180 | from the inductive definition of [c].
181 |
182 | It is also sometimes necessary to add
183 | Hint Unfold d.
184 | where [d] is a defined symbol, so that [auto] knows to expand
185 | uses of [d] and enable further possibilities for applying
186 | lemmas that it knows about. *)
187 |
188 | Hint Resolve le_antisym.
189 |
190 | Example auto_example_6' : forall n m p : nat,
191 | (n<= p -> (n <= m /\ m <= n)) ->
192 | n <= p ->
193 | n = m.
194 | Proof.
195 | intros.
196 | auto. (* picks up hint from database *)
197 | Qed.
198 |
199 | Definition is_fortytwo x := x = 42.
200 |
201 | Example auto_example_7: forall x, (x <= 42 /\ 42 <= x) -> is_fortytwo x.
202 | Proof.
203 | auto. (* does nothing *)
204 | Abort.
205 |
206 | Hint Unfold is_fortytwo.
207 |
208 | Example auto_example_7' : forall x, (x <= 42 /\ 42 <= x) -> is_fortytwo x.
209 | Proof.
210 | info_auto.
211 | Qed.
212 |
213 | Hint Constructors ceval.
214 |
215 | Definition st12 := update (update empty_state X 1) Y 2.
216 | Definition st21 := update (update empty_state X 2) Y 1.
217 |
218 | Example auto_example_8 : exists s',
219 | (IFB (BLe (AId X) (AId Y))
220 | THEN (Z ::= AMinus (AId Y) (AId X))
221 | ELSE (Y ::= APlus (AId X) (AId Z))
222 | FI) / st21 || s'.
223 | Proof.
224 | eexists. info_auto.
225 | Qed.
226 |
227 | Example auto_example_8' : exists s',
228 | (IFB (BLe (AId X) (AId Y))
229 | THEN (Z ::= AMinus (AId Y) (AId X))
230 | ELSE (Y ::= APlus (AId X) (AId Z))
231 | FI) / st12 || s'.
232 | Proof.
233 | eexists. info_auto.
234 | Qed.
235 |
236 |
237 | (** Now let's take a pass over [ceval_deterministic] using [auto]
238 | to simplify the proof script. We see that all simple sequences of hypothesis
239 | applications and all uses of [reflexivity] can be replaced by [auto],
240 | which we add to the default tactic to be applied to each case.
241 | *)
242 |
243 | Theorem ceval_deterministic': forall c st st1 st2,
244 | c / st || st1 ->
245 | c / st || st2 ->
246 | st1 = st2.
247 | Proof.
248 | intros c st st1 st2 E1 E2;
249 | generalize dependent st2;
250 | ceval_cases (induction E1) Case;
251 | intros st2 E2; inv E2; auto.
252 | Case "E_Seq".
253 | assert (st' = st'0) as EQ1.
254 | SCase "Proof of assertion". auto.
255 | subst st'0.
256 | auto.
257 | Case "E_IfTrue".
258 | SCase "b evaluates to false (contradiction)".
259 | rewrite H in H5. inversion H5.
260 | Case "E_IfFalse".
261 | SCase "b evaluates to true (contradiction)".
262 | rewrite H in H5. inversion H5.
263 | Case "E_WhileEnd".
264 | SCase "b evaluates to true (contradiction)".
265 | rewrite H in H2. inversion H2.
266 | Case "E_WhileLoop".
267 | SCase "b evaluates to false (contradiction)".
268 | rewrite H in H4. inversion H4.
269 | SCase "b evaluates to true".
270 | assert (st' = st'0) as EQ1.
271 | SSCase "Proof of assertion". auto.
272 | subst st'0.
273 | auto.
274 | Qed.
275 |
276 | (** When we are using a particular tactic many times in a proof,
277 | we can use a variant of the [Proof] command to make that tactic
278 | into a default within the proof.
279 | Saying [Proof with t] (where [t] is an arbitrary tactic)
280 | allows us to use [t1...] as a shorthand for [t1;t] within the proof.
281 | As an illustration, here is an alternate version of the previous proof,
282 | using [Proof with auto].
283 | *)
284 |
285 | Theorem ceval_deterministic'_alt: forall c st st1 st2,
286 | c / st || st1 ->
287 | c / st || st2 ->
288 | st1 = st2.
289 | Proof with auto.
290 | intros c st st1 st2 E1 E2;
291 | generalize dependent st2;
292 | ceval_cases (induction E1) Case;
293 | intros st2 E2; inv E2...
294 | Case "E_Seq".
295 | assert (st' = st'0) as EQ1.
296 | SCase "Proof of assertion"...
297 | subst st'0...
298 | Case "E_IfTrue".
299 | SCase "b evaluates to false (contradiction)".
300 | rewrite H in H5. inversion H5.
301 | Case "E_IfFalse".
302 | SCase "b evaluates to true (contradiction)".
303 | rewrite H in H5. inversion H5.
304 | Case "E_WhileEnd".
305 | SCase "b evaluates to true (contradiction)".
306 | rewrite H in H2. inversion H2.
307 | Case "E_WhileLoop".
308 | SCase "b evaluates to false (contradiction)".
309 | rewrite H in H4. inversion H4.
310 | SCase "b evaluates to true".
311 | assert (st' = st'0) as EQ1.
312 | SSCase "Proof of assertion"...
313 | subst st'0...
314 | Qed.
315 |
316 | (** * Searching Hypotheses *)
317 |
318 | (** The proof has become simpler, but there is still an annoying amount
319 | of repetition. Let's start by tackling the contradiction cases. Each
320 | of them occurs in a situation where we have both
321 |
322 | [H1: beval st b = false]
323 |
324 | and
325 |
326 | [H2: beval st b = true]
327 |
328 | as hypotheses. The contradiction is evident, but demonstrating it
329 | is a little complicated: we have to locate the two hypotheses [H1] and [H2]
330 | and do a [rewrite] following by an [inversion]. We'd like to automate
331 | this process.
332 |
333 | Note: In fact, Coq has a built-in tactic [congruence] that will do the
334 | job. But we'll ignore the existence of this tactic for now, in order
335 | to demonstrate how to build forward search tactics by hand.
336 |
337 | *)
338 |
339 | (** As a first step, we can abstract out the piece of script in question by
340 | writing a small amount of paramerized Ltac. *)
341 |
342 | Ltac rwinv H1 H2 := rewrite H1 in H2; inv H2.
343 |
344 | Theorem ceval_deterministic'': forall c st st1 st2,
345 | c / st || st1 ->
346 | c / st || st2 ->
347 | st1 = st2.
348 | Proof.
349 | intros c st st1 st2 E1 E2;
350 | generalize dependent st2;
351 | ceval_cases (induction E1) Case;
352 | intros st2 E2; inv E2; auto.
353 | Case "E_Seq".
354 | assert (st' = st'0) as EQ1.
355 | SCase "Proof of assertion". auto.
356 | subst st'0.
357 | auto.
358 | Case "E_IfTrue".
359 | SCase "b evaluates to false (contradiction)".
360 | rwinv H H5.
361 | Case "E_IfFalse".
362 | SCase "b evaluates to true (contradiction)".
363 | rwinv H H5.
364 | Case "E_WhileEnd".
365 | SCase "b evaluates to true (contradiction)".
366 | rwinv H H2.
367 | Case "E_WhileLoop".
368 | SCase "b evaluates to false (contradiction)".
369 | rwinv H H4.
370 | SCase "b evaluates to true".
371 | assert (st' = st'0) as EQ1.
372 | SSCase "Proof of assertion". auto.
373 | subst st'0.
374 | auto. Qed.
375 |
376 |
377 | (** But this is not much better. We really want Coq to discover
378 | the relevant hypotheses for us. We can do this by using the
379 | [match goal with ... end] facility of Ltac. *)
380 |
381 | Ltac find_rwinv :=
382 | match goal with
383 | H1: ?E = true, H2: ?E = false |- _ => rwinv H1 H2
384 | end.
385 |
386 | (** In words, this [match goal] looks for two (distinct) hypotheses that have
387 | the form of equalities with the same arbitrary expression [E] on the
388 | left and conflicting boolean values on the right; if such hypotheses are
389 | found, it binds [H1] and [H2] to their names, and applies the tactic
390 | after the [=>].
391 |
392 | Adding this tactic to our default string handles all the contradiction cases. *)
393 |
394 | Theorem ceval_deterministic''': forall c st st1 st2,
395 | c / st || st1 ->
396 | c / st || st2 ->
397 | st1 = st2.
398 | Proof.
399 | intros c st st1 st2 E1 E2;
400 | generalize dependent st2;
401 | ceval_cases (induction E1) Case;
402 | intros st2 E2; inv E2; try find_rwinv; auto.
403 | Case "E_Seq".
404 | assert (st' = st'0) as EQ1.
405 | SCase "Proof of assertion". auto.
406 | subst st'0.
407 | auto.
408 | Case "E_WhileLoop".
409 | SCase "b evaluates to true".
410 | assert (st' = st'0) as EQ1.
411 | SSCase "Proof of assertion". auto.
412 | subst st'0.
413 | auto. Qed.
414 |
415 | (** Finally, let's see about the remaining cases. Each of them involves
416 | applying a conditional hypothesis to extract an equality. Currently
417 | we have phrased these as assertions, so that we have to predict what
418 | the resulting equality will be (although we can then use [auto]
419 | to prove it.) An alternative is to pick the relevant
420 | hypotheses to use, and then rewrite with them, as follows:
421 | *)
422 |
423 | Theorem ceval_deterministic'''': forall c st st1 st2,
424 | c / st || st1 ->
425 | c / st || st2 ->
426 | st1 = st2.
427 | Proof.
428 | intros c st st1 st2 E1 E2;
429 | generalize dependent st2;
430 | ceval_cases (induction E1) Case;
431 | intros st2 E2; inv E2; try find_rwinv; auto.
432 | Case "E_Seq".
433 | rewrite (IHE1_1 st'0 H1) in *. auto.
434 | Case "E_WhileLoop".
435 | SCase "b evaluates to true".
436 | rewrite (IHE1_1 st'0 H3) in *. auto. Qed.
437 |
438 | (** Now we can automate the task of finding the relevant hypotheses to
439 | rewrite with. *)
440 |
441 | Ltac find_eqn :=
442 | match goal with
443 | H1: forall x, ?P x -> ?L = ?R, H2: ?P ?X |- _ =>
444 | rewrite (H1 X H2) in *
445 | end.
446 |
447 | (** But there are several pairs of hypotheses that have the right
448 | general form, and it seems tricky to pick out the ones we actually need.
449 | A key trick is to realize that we can _try them all_!
450 | Here's how this works:
451 |
452 | - [rewrite] will fail given a trivial equation of the form [X = X].
453 | - each execution of [match goal] will keep trying to find a valid pair of
454 | hypotheses until the tactic on the RHS of the match succeeds;
455 | if there are no such pairs, it fails.
456 | - we can wrap the whole thing in a [repeat] which will keep
457 | doing useful rewrites until only trivial ones are left.
458 | *)
459 |
460 |
461 | Theorem ceval_deterministic''''': forall c st st1 st2,
462 | c / st || st1 ->
463 | c / st || st2 ->
464 | st1 = st2.
465 | Proof.
466 | intros c st st1 st2 E1 E2;
467 | generalize dependent st2;
468 | ceval_cases (induction E1) Case;
469 | intros st2 E2; inv E2; try find_rwinv; repeat find_eqn; auto.
470 | Qed.
471 |
472 | (** The big pay-off in this approach is that our proof script
473 | should be robust in the face of modest changes to our language.
474 | For example, we can add a [REPEAT] command to the language.
475 | (This was an exercise in [Hoare.v].) *)
476 |
477 | Module Repeat.
478 |
479 | Inductive com : Type :=
480 | | CSkip : com
481 | | CAsgn : id -> aexp -> com
482 | | CSeq : com -> com -> com
483 | | CIf : bexp -> com -> com -> com
484 | | CWhile : bexp -> com -> com
485 | | CRepeat : com -> bexp -> com.
486 |
487 | (** [REPEAT] behaves like [WHILE], except that the loop guard is
488 | checked _after_ each execution of the body, with the loop
489 | repeating as long as the guard stays _false_. Because of this,
490 | the body will always execute at least once. *)
491 |
492 | Tactic Notation "com_cases" tactic(first) ident(c) :=
493 | first;
494 | [ Case_aux c "SKIP" | Case_aux c "::=" | Case_aux c ";"
495 | | Case_aux c "IFB" | Case_aux c "WHILE"
496 | | Case_aux c "CRepeat" ].
497 |
498 | Notation "'SKIP'" :=
499 | CSkip.
500 | Notation "c1 ; c2" :=
501 | (CSeq c1 c2) (at level 80, right associativity).
502 | Notation "X '::=' a" :=
503 | (CAsgn X a) (at level 60).
504 | Notation "'WHILE' b 'DO' c 'END'" :=
505 | (CWhile b c) (at level 80, right associativity).
506 | Notation "'IFB' e1 'THEN' e2 'ELSE' e3 'FI'" :=
507 | (CIf e1 e2 e3) (at level 80, right associativity).
508 | Notation "'REPEAT' e1 'UNTIL' b2 'END'" :=
509 | (CRepeat e1 b2) (at level 80, right associativity).
510 |
511 | Inductive ceval : state -> com -> state -> Prop :=
512 | | E_Skip : forall st,
513 | ceval st SKIP st
514 | | E_Ass : forall st a1 n X,
515 | aeval st a1 = n ->
516 | ceval st (X ::= a1) (update st X n)
517 | | E_Seq : forall c1 c2 st st' st'',
518 | ceval st c1 st' ->
519 | ceval st' c2 st'' ->
520 | ceval st (c1 ; c2) st''
521 | | E_IfTrue : forall st st' b1 c1 c2,
522 | beval st b1 = true ->
523 | ceval st c1 st' ->
524 | ceval st (IFB b1 THEN c1 ELSE c2 FI) st'
525 | | E_IfFalse : forall st st' b1 c1 c2,
526 | beval st b1 = false ->
527 | ceval st c2 st' ->
528 | ceval st (IFB b1 THEN c1 ELSE c2 FI) st'
529 | | E_WhileEnd : forall b1 st c1,
530 | beval st b1 = false ->
531 | ceval st (WHILE b1 DO c1 END) st
532 | | E_WhileLoop : forall st st' st'' b1 c1,
533 | beval st b1 = true ->
534 | ceval st c1 st' ->
535 | ceval st' (WHILE b1 DO c1 END) st'' ->
536 | ceval st (WHILE b1 DO c1 END) st''
537 | | E_RepeatEnd : forall st st' b1 c1,
538 | ceval st c1 st' ->
539 | beval st' b1 = true ->
540 | ceval st (CRepeat c1 b1) st'
541 | | E_RepeatLoop : forall st st' st'' b1 c1,
542 | ceval st c1 st' ->
543 | beval st' b1 = false ->
544 | ceval st' (CRepeat c1 b1) st'' ->
545 | ceval st (CRepeat c1 b1) st''
546 | .
547 |
548 | Tactic Notation "ceval_cases" tactic(first) ident(c) :=
549 | first;
550 | [ Case_aux c "E_Skip" | Case_aux c "E_Ass"
551 | | Case_aux c "E_Seq"
552 | | Case_aux c "E_IfTrue" | Case_aux c "E_IfFalse"
553 | | Case_aux c "E_WhileEnd" | Case_aux c "E_WhileLoop"
554 | | Case_aux c "E_RepeatEnd" | Case_aux c "E_RepeatLoop"
555 | ].
556 |
557 | Notation "c1 '/' st '||' st'" := (ceval st c1 st')
558 | (at level 40, st at level 39).
559 |
560 |
561 | Theorem ceval_deterministic: forall c st st1 st2,
562 | c / st || st1 ->
563 | c / st || st2 ->
564 | st1 = st2.
565 | Proof.
566 | intros c st st1 st2 E1 E2;
567 | generalize dependent st2;
568 | ceval_cases (induction E1) Case;
569 | intros st2 E2; inv E2; try find_rwinv; repeat find_eqn; auto.
570 | Case "E_RepeatEnd".
571 | SCase "b evaluates to false (contradiction)".
572 | find_rwinv.
573 | (* oops: why didn't [find_rwinv] solve this for us already?
574 | answer: we did things in the wrong order. *)
575 | case "E_RepeatLoop".
576 | SCase "b evaluates to true (contradiction)".
577 | find_rwinv.
578 | Qed.
579 |
580 | Theorem ceval_deterministic': forall c st st1 st2,
581 | c / st || st1 ->
582 | c / st || st2 ->
583 | st1 = st2.
584 | Proof.
585 | intros c st st1 st2 E1 E2;
586 | generalize dependent st2;
587 | ceval_cases (induction E1) Case;
588 | intros st2 E2; inv E2; repeat find_eqn; try find_rwinv; auto.
589 | Qed.
590 |
591 | End Repeat.
592 |
593 | (** These examples just give a flavor of what "hyper-automation" can do...
594 |
595 | The details of using [match goal] are tricky, and debugging is
596 | not pleasant at all. But it is well worth adding at least simple
597 | uses to your proofs to avoid tedium and "future proof" your scripts.
598 |
599 | *)
600 |
601 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
602 |
--------------------------------------------------------------------------------
/Extraction.v:
--------------------------------------------------------------------------------
1 | (** * Extraction: Extracting ML from Coq *)
2 |
3 | (** * Basic Extraction *)
4 |
5 | (** In its simplest form, program extraction from Coq is completely straightforward. *)
6 |
7 | (** First we say what language we want to extract into. Options are OCaml (the
8 | most mature), Haskell (which mostly works), and Scheme (a bit out
9 | of date). *)
10 |
11 | Extraction Language Ocaml.
12 |
13 | (** Now we load up the Coq environment with some definitions, either
14 | directly or by importing them from other modules. *)
15 |
16 | Require Import SfLib.
17 | Require Import ImpCEvalFun.
18 |
19 | (** Finally, we tell Coq the name of a definition to extract and the
20 | name of a file to put the extracted code into. *)
21 |
22 | Extraction "imp1.ml" ceval_step.
23 |
24 | (** When Coq processes this command, it generates a file [imp1.ml]
25 | containing an extracted version of [ceval_step], together with
26 | everything that it recursively depends on. Have a look at this
27 | file now. *)
28 |
29 | (* ############################################################## *)
30 | (** * Controlling Extraction of Specific Types *)
31 |
32 | (** We can tell Coq to extract certain [Inductive] definitions to
33 | specific OCaml types. For each one, we must say
34 | - how the Coq type itself should be represented in OCaml, and
35 | - how each constructor should be translated. *)
36 |
37 | Extract Inductive bool => "bool" [ "true" "false" ].
38 |
39 | (** Also, for non-enumeration types (where the constructors take
40 | arguments), we give an OCaml expression that can be used as a
41 | "recursor" over elements of the type. (Think Church numerals.) *)
42 |
43 | Extract Inductive nat => "int"
44 | [ "0" "(fun x -> x + 1)" ]
45 | "(fun zero succ n ->
46 | if n=0 then zero () else succ (n-1))".
47 |
48 | (** We can also extract defined constants to specific OCaml terms or
49 | operators. *)
50 |
51 | Extract Constant plus => "( + )".
52 | Extract Constant mult => "( * )".
53 | Extract Constant beq_nat => "( = )".
54 |
55 | (** Important: It is entirely _your responsibility_ to make sure that
56 | the translations you're proving make sense. For example, it might
57 | be tempting to include this one
58 | Extract Constant minus => "( - )".
59 | but doing so could lead to serious confusion! (Why?)
60 | *)
61 |
62 | Extraction "imp2.ml" ceval_step.
63 |
64 | (** Have a look at the file [imp2.ml]. Notice how the fundamental
65 | definitions have changed from [imp1.ml]. *)
66 |
67 | (* ############################################################## *)
68 | (** * A Complete Example *)
69 |
70 | (** To use our extracted evaluator to run Imp programs, all we need to
71 | add is a tiny driver program that calls the evaluator and somehow
72 | prints out the result.
73 |
74 | For simplicity, we'll print results by dumping out the first four
75 | memory locations in the final state.
76 |
77 | Also, to make it easier to type in examples, let's extract a
78 | parser from the [ImpParser] Coq module. To do this, we need a few
79 | more declarations to set up the right correspondence between Coq
80 | strings and lists of OCaml characters. *)
81 |
82 | Require Import Ascii String.
83 | Extract Inductive ascii => char
84 | [
85 | "(* If this appears, you're using Ascii internals. Please don't *) (fun (b0,b1,b2,b3,b4,b5,b6,b7) -> let f b i = if b then 1 lsl i else 0 in Char.chr (f b0 0 + f b1 1 + f b2 2 + f b3 3 + f b4 4 + f b5 5 + f b6 6 + f b7 7))"
86 | ]
87 | "(* If this appears, you're using Ascii internals. Please don't *) (fun f c -> let n = Char.code c in let h i = (n land (1 lsl i)) <> 0 in f (h 0) (h 1) (h 2) (h 3) (h 4) (h 5) (h 6) (h 7))".
88 | Extract Constant zero => "'\000'".
89 | Extract Constant one => "'\001'".
90 | Extract Constant shift =>
91 | "fun b c -> Char.chr (((Char.code c) lsl 1) land 255 + if b then 1 else 0)".
92 | Extract Inlined Constant ascii_dec => "(=)".
93 |
94 | (** We also need one more variant of booleans. *)
95 |
96 | Extract Inductive sumbool => "bool" ["true" "false"].
97 |
98 | (** The extraction is the same as always. *)
99 |
100 | Require Import Imp.
101 | Require Import ImpParser.
102 | Extraction "imp.ml" empty_state ceval_step parse.
103 |
104 | (** Now let's run our generated Imp evaluator. First, have a look at
105 | [impdriver.ml]. (This was written by hand, not extracted.)
106 |
107 | Next, compile the driver together with the extracted code and
108 | execute it, as follows.
109 | <<
110 | ocamlc -w -20 -w -26 -o impdriver imp.mli imp.ml impdriver.ml
111 | ./impdriver
112 | >>
113 | (The [-w] flags to [ocamlc] are just there to suppress a few
114 | spurious warnings.) *)
115 |
116 | (* ############################################################## *)
117 | (** * Discussion *)
118 |
119 | (** Since we've proved that the [ceval_step] function behaves the same
120 | as the [ceval] relation in an appropriate sense, the extracted
121 | program can be viewed as a _certified_ Imp interpreter. (Of
122 | course, the parser is not certified in any interesting sense,
123 | since we didn't prove anything about it.) *)
124 |
125 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
126 |
--------------------------------------------------------------------------------
/HoareAsLogic.v:
--------------------------------------------------------------------------------
1 | (** * HoareAsLogic: Hoare Logic as a Logic *)
2 |
3 | Require Export Hoare.
4 |
5 | (** The presentation of Hoare logic in chapter [Hoare] could be
6 | described as "model-theoretic": the proof rules for each of the
7 | constructors were presented as _theorems_ about the evaluation
8 | behavior of programs, and proofs of program correctness (validity
9 | of Hoare triples) were constructed by combining these theorems
10 | directly in Coq.
11 |
12 | Another way of presenting Hoare logic is to define a completely
13 | separate proof system -- a set of axioms and inference rules that
14 | talk about commands, Hoare triples, etc. -- and then say that a
15 | proof of a Hoare triple is a valid derivation in _that_ logic. We
16 | can do this by giving an inductive definition of _valid
17 | derivations_ in this new logic. *)
18 |
19 | Inductive hoare_proof : Assertion -> com -> Assertion -> Type :=
20 | | H_Skip : forall P,
21 | hoare_proof P (SKIP) P
22 | | H_Asgn : forall Q V a,
23 | hoare_proof (assn_sub V a Q) (V ::= a) Q
24 | | H_Seq : forall P c Q d R,
25 | hoare_proof P c Q -> hoare_proof Q d R -> hoare_proof P (c;;d) R
26 | | H_If : forall P Q b c1 c2,
27 | hoare_proof (fun st => P st /\ bassn b st) c1 Q ->
28 | hoare_proof (fun st => P st /\ ~(bassn b st)) c2 Q ->
29 | hoare_proof P (IFB b THEN c1 ELSE c2 FI) Q
30 | | H_While : forall P b c,
31 | hoare_proof (fun st => P st /\ bassn b st) c P ->
32 | hoare_proof P (WHILE b DO c END) (fun st => P st /\ ~ (bassn b st))
33 | | H_Consequence : forall (P Q P' Q' : Assertion) c,
34 | hoare_proof P' c Q' ->
35 | (forall st, P st -> P' st) ->
36 | (forall st, Q' st -> Q st) ->
37 | hoare_proof P c Q.
38 |
39 | Tactic Notation "hoare_proof_cases" tactic(first) ident(c) :=
40 | first;
41 | [ Case_aux c "H_Skip" | Case_aux c "H_Asgn" | Case_aux c "H_Seq"
42 | | Case_aux c "H_If" | Case_aux c "H_While" | Case_aux c "H_Consequence" ].
43 |
44 | (** We don't need to include axioms corresponding to [hoare_consequence_pre]
45 | or [hoare_consequence_post], because these can be proven easily
46 | from [H_Consequence]. *)
47 |
48 | Lemma H_Consequence_pre : forall (P Q P': Assertion) c,
49 | hoare_proof P' c Q ->
50 | (forall st, P st -> P' st) ->
51 | hoare_proof P c Q.
52 | Proof.
53 | intros. eapply H_Consequence. apply X. assumption.
54 | intros; assumption.
55 | Qed.
56 |
57 | Lemma H_Consequence_post : forall (P Q Q' : Assertion) c,
58 | hoare_proof P c Q' ->
59 | (forall st, Q' st -> Q st) ->
60 | hoare_proof P c Q.
61 | Proof.
62 | intros. eapply H_Consequence. apply X. intros; assumption.
63 | assumption.
64 | Qed.
65 |
66 |
67 | (** Now, for example, let's construct a proof object representing a
68 | derivation for the hoare triple
69 | {{assn_sub X (X+1) (assn_sub X (X+2) (X=3))}} X::=X+1;; X::=X+2 {{X=3}}.
70 | We can use Coq's tactics to help us construct the proof object. *)
71 |
72 | Example sample_proof
73 | : hoare_proof
74 | (assn_sub X (APlus (AId X) (ANum 1))
75 | (assn_sub X (APlus (AId X) (ANum 2))
76 | (fun st => st X = 3) ))
77 | (X ::= APlus (AId X) (ANum 1);; (X ::= APlus (AId X) (ANum 2)))
78 | (fun st => st X = 3).
79 | Proof.
80 | eapply H_Seq; apply H_Asgn.
81 | Qed.
82 |
83 |
84 | (*
85 | Print sample_proof.
86 | ====>
87 | H_Seq
88 | (assn_sub X (APlus (AId X) (ANum 1))
89 | (assn_sub X (APlus (AId X) (ANum 2)) (fun st : state => st X = VNat 3)))
90 | (X ::= APlus (AId X) (ANum 1))
91 | (assn_sub X (APlus (AId X) (ANum 2)) (fun st : state => st X = VNat 3))
92 | (X ::= APlus (AId X) (ANum 2)) (fun st : state => st X = VNat 3)
93 | (H_Asgn
94 | (assn_sub X (APlus (AId X) (ANum 2)) (fun st : state => st X = VNat 3))
95 | X (APlus (AId X) (ANum 1)))
96 | (H_Asgn (fun st : state => st X = VNat 3) X (APlus (AId X) (ANum 2)))
97 | *)
98 |
99 | (** **** Exercise: 2 stars (hoare_proof_sound) *)
100 | (** Prove that such proof objects represent true claims. *)
101 |
102 | Theorem hoare_proof_sound : forall P c Q,
103 | hoare_proof P c Q -> {{P}} c {{Q}}.
104 | Proof.
105 | intros. induction X.
106 | apply hoare_skip.
107 | apply hoare_asgn.
108 | eapply hoare_seq. eauto. assumption.
109 | apply hoare_if; assumption.
110 | apply hoare_while. assumption.
111 | eapply hoare_consequence_post.
112 | eapply hoare_consequence_pre.
113 | eauto. assumption. assumption.
114 | Qed.
115 | (** [] *)
116 |
117 | (** We can also use Coq's reasoning facilities to prove metatheorems
118 | about Hoare Logic. For example, here are the analogs of two
119 | theorems we saw in chapter [Hoare] -- this time expressed in terms
120 | of the syntax of Hoare Logic derivations (provability) rather than
121 | directly in terms of the semantics of Hoare triples.
122 |
123 | The first one says that, for every [P] and [c], the assertion
124 | [{{P}} c {{True}}] is _provable_ in Hoare Logic. Note that the
125 | proof is more complex than the semantic proof in [Hoare]: we
126 | actually need to perform an induction over the structure of the
127 | command [c]. *)
128 |
129 | Theorem H_Post_True_deriv:
130 | forall c P, hoare_proof P c (fun _ => True).
131 | Proof.
132 | intro c.
133 | com_cases (induction c) Case; intro P.
134 | Case "SKIP".
135 | eapply H_Consequence.
136 | apply H_Skip.
137 | intros. apply H.
138 | (* Proof of True *)
139 | intros. apply I.
140 | Case "::=".
141 | eapply H_Consequence_pre.
142 | apply H_Asgn.
143 | intros. apply I.
144 | Case ";;".
145 | eapply H_Consequence_pre.
146 | eapply H_Seq.
147 | apply (IHc1 (fun _ => True)).
148 | apply IHc2.
149 | intros. apply I.
150 | Case "IFB".
151 | apply H_Consequence_pre with (fun _ => True).
152 | apply H_If.
153 | apply IHc1.
154 | apply IHc2.
155 | intros. apply I.
156 | Case "WHILE".
157 | eapply H_Consequence.
158 | eapply H_While.
159 | eapply IHc.
160 | intros; apply I.
161 | intros; apply I.
162 | Qed.
163 |
164 | (** Similarly, we can show that [{{False}} c {{Q}}] is provable for
165 | any [c] and [Q]. *)
166 |
167 | Lemma False_and_P_imp: forall P Q,
168 | False /\ P -> Q.
169 | Proof.
170 | intros P Q [CONTRA HP].
171 | destruct CONTRA.
172 | Qed.
173 |
174 | Tactic Notation "pre_false_helper" constr(CONSTR) :=
175 | eapply H_Consequence_pre;
176 | [eapply CONSTR | intros ? CONTRA; destruct CONTRA].
177 |
178 | Theorem H_Pre_False_deriv:
179 | forall c Q, hoare_proof (fun _ => False) c Q.
180 | Proof.
181 | intros c.
182 | com_cases (induction c) Case; intro Q.
183 | Case "SKIP". pre_false_helper H_Skip.
184 | Case "::=". pre_false_helper H_Asgn.
185 | Case ";;". pre_false_helper H_Seq. apply IHc1. apply IHc2.
186 | Case "IFB".
187 | apply H_If; eapply H_Consequence_pre.
188 | apply IHc1. intro. eapply False_and_P_imp.
189 | apply IHc2. intro. eapply False_and_P_imp.
190 | Case "WHILE".
191 | eapply H_Consequence_post.
192 | eapply H_While.
193 | eapply H_Consequence_pre.
194 | apply IHc.
195 | intro. eapply False_and_P_imp.
196 | intro. simpl. eapply False_and_P_imp.
197 | Qed.
198 |
199 | (** As a last step, we can show that the set of [hoare_proof] axioms is
200 | sufficient to prove any true fact about (partial) correctness.
201 | More precisely, any semantic Hoare triple that we can prove can
202 | also be proved from these axioms. Such a set of axioms is said
203 | to be _relatively complete_. *)
204 |
205 | (** This proof is inspired by the one at
206 | http://www.ps.uni-saarland.de/courses/sem-ws11/script/Hoare.html
207 | *)
208 |
209 | (** To prove this fact, we'll need to invent some intermediate
210 | assertions using a technical device known as _weakest preconditions_.
211 | Given a command [c] and a desired postcondition assertion [Q],
212 | the weakest precondition [wp c Q] is an assertion [P] such that
213 | [{{P}} c {{Q}}] holds, and moreover, for any other assertion [P'],
214 | if [{{P'}} c {{Q}}] holds then [P' -> P]. We can more directly
215 | define this as follows: *)
216 |
217 | Definition wp (c:com) (Q:Assertion) : Assertion :=
218 | fun s => forall s', c / s || s' -> Q s'.
219 |
220 | (** **** Exercise: 1 star (wp_is_precondition) *)
221 |
222 | Lemma wp_is_precondition: forall c Q,
223 | {{wp c Q}} c {{Q}}.
224 | Proof.
225 | unfold wp. intros c Q st st' H H1.
226 | apply H1. assumption.
227 | Qed.
228 | (** [] *)
229 |
230 | (** **** Exercise: 1 star (wp_is_weakest) *)
231 |
232 | Lemma wp_is_weakest: forall c Q P',
233 | {{P'}} c {{Q}} -> forall st, P' st -> wp c Q st.
234 | Proof.
235 | unfold hoare_triple. unfold wp.
236 | intros. eapply H. eauto. assumption.
237 | Qed.
238 |
239 | (** The following utility lemma will also be useful. *)
240 |
241 | Lemma bassn_eval_false : forall b st, ~ bassn b st -> beval st b = false.
242 | Proof.
243 | intros b st H. unfold bassn in H. destruct (beval st b).
244 | exfalso. apply H. reflexivity.
245 | reflexivity.
246 | Qed.
247 | (** [] *)
248 |
249 | (** **** Exercise: 4 stars (hoare_proof_complete) *)
250 | (** Complete the proof of the theorem. *)
251 |
252 | Theorem hoare_proof_complete: forall P c Q,
253 | {{P}} c {{Q}} -> hoare_proof P c Q.
254 | Proof.
255 | intros P c. generalize dependent P.
256 | com_cases (induction c) Case; intros P Q HT.
257 | Case "SKIP".
258 | eapply H_Consequence.
259 | eapply H_Skip.
260 | intros. eassumption.
261 | intro st. apply HT. apply E_Skip.
262 | Case "::=".
263 | eapply H_Consequence.
264 | eapply H_Asgn.
265 | intro st. apply HT. econstructor. reflexivity.
266 | intros; assumption.
267 | Case ";;".
268 | apply H_Seq with (wp c2 Q).
269 | eapply IHc1.
270 | intros st st' E1 H. unfold wp. intros st'' E2.
271 | eapply HT. econstructor; eassumption. assumption.
272 | eapply IHc2. intros st st' E1 H. apply H; assumption.
273 | Case "IFB".
274 | apply H_If.
275 | apply IHc1. intros st st' H1 H2. destruct H2.
276 | eapply HT; eauto. apply E_IfTrue; auto.
277 | apply IHc2. intros st st' H1 H2. destruct H2.
278 | eapply HT; eauto. apply E_IfFalse; auto. eapply bassn_eval_false. assumption.
279 | Case "WHILE".
280 | eapply H_Consequence with (P' := wp (WHILE b DO c END) Q).
281 | apply H_While. apply IHc. intros st st' H H'.
282 | destruct H'. unfold wp in *. intros.
283 | apply H0. eapply E_WhileLoop. assumption. eassumption.
284 | assumption.
285 | apply wp_is_weakest. assumption.
286 | simpl. intros. destruct H.
287 | apply wp_is_precondition with (WHILE b DO c END) st.
288 | apply E_WhileEnd. apply bassn_eval_false. assumption. assumption.
289 | Qed.
290 | (** [] *)
291 |
292 | (** Finally, we might hope that our axiomatic Hoare logic is _decidable_;
293 | that is, that there is an (terminating) algorithm (a _decision procedure_)
294 | that can determine whether or not a given Hoare triple is valid (derivable).
295 | But such a decision procedure cannot exist!
296 |
297 | Consider the triple [{{True}} c {{False}}]. This triple is valid
298 | if and only if [c] is non-terminating. So any algorithm that could
299 | determine validity of arbitrary triples could solve the Halting Problem.
300 |
301 | Similarly, the triple [{{True} SKIP {{P}}] is valid if and only if
302 | [forall s, P s] is valid, where [P] is an arbitrary assertion of Coq's
303 | logic. But it is known that there can be no decision procedure for
304 | this logic.
305 |
306 | *)
307 |
308 | (** Overall, this axiomatic style of presentation gives a clearer picture of what it
309 | means to "give a proof in Hoare logic." However, it is not
310 | entirely satisfactory from the point of view of writing down such
311 | proofs in practice: it is quite verbose. The section of chapter
312 | [Hoare2] on formalizing decorated programs shows how we can do even
313 | better. *)
314 |
315 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
316 |
--------------------------------------------------------------------------------
/ImpCEvalFun.v:
--------------------------------------------------------------------------------
1 | (** * ImpCEvalFun: Evaluation Function for Imp *)
2 |
3 | (* #################################### *)
4 | (** * Evaluation Function *)
5 |
6 | Require Import Imp.
7 |
8 | (** Here's a first try at an evaluation function for commands,
9 | omitting [WHILE]. *)
10 |
11 | Fixpoint ceval_step1 (st : state) (c : com) : state :=
12 | match c with
13 | | SKIP =>
14 | st
15 | | l ::= a1 =>
16 | update st l (aeval st a1)
17 | | c1 ;; c2 =>
18 | let st' := ceval_step1 st c1 in
19 | ceval_step1 st' c2
20 | | IFB b THEN c1 ELSE c2 FI =>
21 | if (beval st b)
22 | then ceval_step1 st c1
23 | else ceval_step1 st c2
24 | | WHILE b1 DO c1 END =>
25 | st (* bogus *)
26 | end.
27 |
28 | (** In a traditional functional programming language like ML or
29 | Haskell we could write the WHILE case as follows:
30 | <<
31 | | WHILE b1 DO c1 END =>
32 | if (beval st b1)
33 | then ceval_step1 st (c1;; WHILE b1 DO c1 END)
34 | else st
35 | >>
36 | Coq doesn't accept such a definition ([Error: Cannot guess
37 | decreasing argument of fix]) because the function we want to
38 | define is not guaranteed to terminate. Indeed, the changed
39 | [ceval_step1] function applied to the [loop] program from [Imp.v] would
40 | never terminate. Since Coq is not just a functional programming
41 | language, but also a consistent logic, any potentially
42 | non-terminating function needs to be rejected. Here is an
43 | invalid(!) Coq program showing what would go wrong if Coq allowed
44 | non-terminating recursive functions:
45 | <<
46 | Fixpoint loop_false (n : nat) : False := loop_false n.
47 | >>
48 | That is, propositions like [False] would become
49 | provable (e.g. [loop_false 0] would be a proof of [False]), which
50 | would be a disaster for Coq's logical consistency.
51 |
52 | Thus, because it doesn't terminate on all inputs, the full version
53 | of [ceval_step1] cannot be written in Coq -- at least not
54 | without one additional trick... *)
55 |
56 |
57 | (** Second try, using an extra numeric argument as a "step index" to
58 | ensure that evaluation always terminates. *)
59 |
60 | Fixpoint ceval_step2 (st : state) (c : com) (i : nat) : state :=
61 | match i with
62 | | O => empty_state
63 | | S i' =>
64 | match c with
65 | | SKIP =>
66 | st
67 | | l ::= a1 =>
68 | update st l (aeval st a1)
69 | | c1 ;; c2 =>
70 | let st' := ceval_step2 st c1 i' in
71 | ceval_step2 st' c2 i'
72 | | IFB b THEN c1 ELSE c2 FI =>
73 | if (beval st b)
74 | then ceval_step2 st c1 i'
75 | else ceval_step2 st c2 i'
76 | | WHILE b1 DO c1 END =>
77 | if (beval st b1)
78 | then let st' := ceval_step2 st c1 i' in
79 | ceval_step2 st' c i'
80 | else st
81 | end
82 | end.
83 |
84 | (** _Note_: It is tempting to think that the index [i] here is
85 | counting the "number of steps of evaluation." But if you look
86 | closely you'll see that this is not the case: for example, in the
87 | rule for sequencing, the same [i] is passed to both recursive
88 | calls. Understanding the exact way that [i] is treated will be
89 | important in the proof of [ceval__ceval_step], which is given as
90 | an exercise below. *)
91 |
92 | (** Third try, returning an [option state] instead of just a [state]
93 | so that we can distinguish between normal and abnormal
94 | termination. *)
95 |
96 | Fixpoint ceval_step3 (st : state) (c : com) (i : nat)
97 | : option state :=
98 | match i with
99 | | O => None
100 | | S i' =>
101 | match c with
102 | | SKIP =>
103 | Some st
104 | | l ::= a1 =>
105 | Some (update st l (aeval st a1))
106 | | c1 ;; c2 =>
107 | match (ceval_step3 st c1 i') with
108 | | Some st' => ceval_step3 st' c2 i'
109 | | None => None
110 | end
111 | | IFB b THEN c1 ELSE c2 FI =>
112 | if (beval st b)
113 | then ceval_step3 st c1 i'
114 | else ceval_step3 st c2 i'
115 | | WHILE b1 DO c1 END =>
116 | if (beval st b1)
117 | then match (ceval_step3 st c1 i') with
118 | | Some st' => ceval_step3 st' c i'
119 | | None => None
120 | end
121 | else Some st
122 | end
123 | end.
124 |
125 | (** We can improve the readability of this definition by introducing a
126 | bit of auxiliary notation to hide the "plumbing" involved in
127 | repeatedly matching against optional states. *)
128 |
129 | Notation "'LETOPT' x <== e1 'IN' e2"
130 | := (match e1 with
131 | | Some x => e2
132 | | None => None
133 | end)
134 | (right associativity, at level 60).
135 |
136 | Fixpoint ceval_step (st : state) (c : com) (i : nat)
137 | : option state :=
138 | match i with
139 | | O => None
140 | | S i' =>
141 | match c with
142 | | SKIP =>
143 | Some st
144 | | l ::= a1 =>
145 | Some (update st l (aeval st a1))
146 | | c1 ;; c2 =>
147 | LETOPT st' <== ceval_step st c1 i' IN
148 | ceval_step st' c2 i'
149 | | IFB b THEN c1 ELSE c2 FI =>
150 | if (beval st b)
151 | then ceval_step st c1 i'
152 | else ceval_step st c2 i'
153 | | WHILE b1 DO c1 END =>
154 | if (beval st b1)
155 | then LETOPT st' <== ceval_step st c1 i' IN
156 | ceval_step st' c i'
157 | else Some st
158 | end
159 | end.
160 |
161 | Definition test_ceval (st:state) (c:com) :=
162 | match ceval_step st c 500 with
163 | | None => None
164 | | Some st => Some (st X, st Y, st Z)
165 | end.
166 |
167 | (* Eval compute in
168 | (test_ceval empty_state
169 | (X ::= ANum 2;;
170 | IFB BLe (AId X) (ANum 1)
171 | THEN Y ::= ANum 3
172 | ELSE Z ::= ANum 4
173 | FI)).
174 | ====>
175 | Some (2, 0, 4) *)
176 |
177 | (** **** Exercise: 2 stars (pup_to_n) *)
178 | (** Write an Imp program that sums the numbers from [1] to
179 | [X] (inclusive: [1 + 2 + ... + X]) in the variable [Y]. Make sure
180 | your solution satisfies the test that follows. *)
181 |
182 | Definition pup_to_n : com :=
183 | Y ::= (ANum 0);;
184 | WHILE BLe (ANum 1) (AId X) DO
185 | Y ::= APlus (AId Y) (AId X);;
186 | X ::= AMinus (AId X) (ANum 1)
187 | END.
188 |
189 | Example pup_to_n_1 :
190 | test_ceval (update empty_state X 5) pup_to_n
191 | = Some (0, 15, 0).
192 | Proof. reflexivity. Qed.
193 | (** [] *)
194 |
195 | (** **** Exercise: 2 stars, optional (peven) *)
196 | (** Write a [While] program that sets [Z] to [0] if [X] is even and
197 | sets [Z] to [1] otherwise. Use [ceval_test] to test your
198 | program. *)
199 |
200 | Definition peven : com :=
201 | WHILE BLe (ANum 2) (AId X) DO
202 | X ::= AMinus (AId X) (ANum 2)
203 | END;;
204 | IFB BEq (ANum 1) (AId X) THEN
205 | Z ::= (ANum 1) ELSE Z ::= (ANum 0)
206 | FI.
207 |
208 | Example peven_11:
209 | test_ceval (update empty_state X 11) peven
210 | = Some (1, 0, 1).
211 | Proof. reflexivity. Qed.
212 |
213 | Example peven_10:
214 | test_ceval (update empty_state X 10) peven
215 | = Some (0, 0, 0).
216 | Proof. reflexivity. Qed.
217 | (** [] *)
218 |
219 | (* ################################################################ *)
220 | (** * Equivalence of Relational and Step-Indexed Evaluation *)
221 |
222 | (** As with arithmetic and boolean expressions, we'd hope that
223 | the two alternative definitions of evaluation actually boil down
224 | to the same thing. This section shows that this is the case.
225 | Make sure you understand the statements of the theorems and can
226 | follow the structure of the proofs. *)
227 |
228 | Theorem ceval_step__ceval: forall c st st',
229 | (exists i, ceval_step st c i = Some st') ->
230 | c / st || st'.
231 | Proof.
232 | intros c st st' H.
233 | inversion H as [i E].
234 | clear H.
235 | generalize dependent st'.
236 | generalize dependent st.
237 | generalize dependent c.
238 | induction i as [| i' ].
239 |
240 | Case "i = 0 -- contradictory".
241 | intros c st st' H. inversion H.
242 |
243 | Case "i = S i'".
244 | intros c st st' H.
245 | com_cases (destruct c) SCase;
246 | simpl in H; inversion H; subst; clear H.
247 | SCase "SKIP". apply E_Skip.
248 | SCase "::=". apply E_Ass. reflexivity.
249 |
250 | SCase ";;".
251 | destruct (ceval_step st c1 i') eqn:Heqr1.
252 | SSCase "Evaluation of r1 terminates normally".
253 | apply E_Seq with s.
254 | apply IHi'. rewrite Heqr1. reflexivity.
255 | apply IHi'. simpl in H1. assumption.
256 | SSCase "Otherwise -- contradiction".
257 | inversion H1.
258 |
259 | SCase "IFB".
260 | destruct (beval st b) eqn:Heqr.
261 | SSCase "r = true".
262 | apply E_IfTrue. rewrite Heqr. reflexivity.
263 | apply IHi'. assumption.
264 | SSCase "r = false".
265 | apply E_IfFalse. rewrite Heqr. reflexivity.
266 | apply IHi'. assumption.
267 |
268 | SCase "WHILE". destruct (beval st b) eqn :Heqr.
269 | SSCase "r = true".
270 | destruct (ceval_step st c i') eqn:Heqr1.
271 | SSSCase "r1 = Some s".
272 | apply E_WhileLoop with s. rewrite Heqr. reflexivity.
273 | apply IHi'. rewrite Heqr1. reflexivity.
274 | apply IHi'. simpl in H1. assumption.
275 | SSSCase "r1 = None".
276 | inversion H1.
277 | SSCase "r = false".
278 | inversion H1.
279 | apply E_WhileEnd.
280 | rewrite <- Heqr. subst. reflexivity. Qed.
281 |
282 | (** **** Exercise: 4 stars (ceval_step__ceval_inf) *)
283 | (** Write an informal proof of [ceval_step__ceval], following the
284 | usual template. (The template for case analysis on an inductively
285 | defined value should look the same as for induction, except that
286 | there is no induction hypothesis.) Make your proof communicate
287 | the main ideas to a human reader; do not simply transcribe the
288 | steps of the formal proof.
289 |
290 | ...
291 | []
292 | *)
293 |
294 | Theorem ceval_step_more: forall i1 i2 st st' c,
295 | i1 <= i2 ->
296 | ceval_step st c i1 = Some st' ->
297 | ceval_step st c i2 = Some st'.
298 | Proof.
299 | induction i1 as [|i1']; intros i2 st st' c Hle Hceval.
300 | Case "i1 = 0".
301 | simpl in Hceval. inversion Hceval.
302 | Case "i1 = S i1'".
303 | destruct i2 as [|i2']. inversion Hle.
304 | assert (Hle': i1' <= i2') by omega.
305 | com_cases (destruct c) SCase.
306 | SCase "SKIP".
307 | simpl in Hceval. inversion Hceval.
308 | reflexivity.
309 | SCase "::=".
310 | simpl in Hceval. inversion Hceval.
311 | reflexivity.
312 | SCase ";;".
313 | simpl in Hceval. simpl.
314 | destruct (ceval_step st c1 i1') eqn:Heqst1'o.
315 | SSCase "st1'o = Some".
316 | apply (IHi1' i2') in Heqst1'o; try assumption.
317 | rewrite Heqst1'o. simpl. simpl in Hceval.
318 | apply (IHi1' i2') in Hceval; try assumption.
319 | SSCase "st1'o = None".
320 | inversion Hceval.
321 |
322 | SCase "IFB".
323 | simpl in Hceval. simpl.
324 | destruct (beval st b); apply (IHi1' i2') in Hceval; assumption.
325 |
326 | SCase "WHILE".
327 | simpl in Hceval. simpl.
328 | destruct (beval st b); try assumption.
329 | destruct (ceval_step st c i1') eqn: Heqst1'o.
330 | SSCase "st1'o = Some".
331 | apply (IHi1' i2') in Heqst1'o; try assumption.
332 | rewrite -> Heqst1'o. simpl. simpl in Hceval.
333 | apply (IHi1' i2') in Hceval; try assumption.
334 | SSCase "i1'o = None".
335 | simpl in Hceval. inversion Hceval. Qed.
336 |
337 | (** **** Exercise: 3 stars (ceval__ceval_step) *)
338 | (** Finish the following proof. You'll need [ceval_step_more] in a
339 | few places, as well as some basic facts about [<=] and [plus]. *)
340 |
341 | Theorem ceval__ceval_step: forall c st st',
342 | c / st || st' ->
343 | exists i, ceval_step st c i = Some st'.
344 | Proof.
345 | intros c st st' Hce.
346 | ceval_cases (induction Hce) Case.
347 | exists 1. reflexivity. exists 1. simpl. rewrite H. reflexivity.
348 | destruct IHHce1. destruct IHHce2.
349 | exists (1 + x + x0). simpl. destruct (ceval_step st c1 (x + x0)) eqn:eqstep.
350 | apply ceval_step_more with (i2 := x + x0) in H.
351 | rewrite H in eqstep. inversion eqstep. subst.
352 | apply ceval_step_more with (i1 := x0). omega. assumption. omega.
353 | apply ceval_step_more with (i2 := x + x0) in H.
354 | rewrite eqstep in H. inversion H. omega.
355 | destruct IHHce. exists (1 + x). simpl. rewrite H. assumption.
356 | destruct IHHce. exists (1 + x). simpl. rewrite H. assumption.
357 | exists 1. simpl. rewrite H. reflexivity.
358 | destruct IHHce1. destruct IHHce2.
359 | exists (1 + x + x0). simpl. rewrite H.
360 | destruct (ceval_step st c (x + x0)) eqn:eqstep.
361 | apply ceval_step_more with (i2 := x + x0) in H0.
362 | rewrite eqstep in H0. inversion H0.
363 | apply ceval_step_more with (i1 := x0). omega. assumption. omega.
364 | apply ceval_step_more with (i2 := x + x0) in H0.
365 | rewrite H0 in eqstep. inversion eqstep. omega.
366 | Qed.
367 |
368 | (** [] *)
369 |
370 | Theorem ceval_and_ceval_step_coincide: forall c st st',
371 | c / st || st'
372 | <-> exists i, ceval_step st c i = Some st'.
373 | Proof.
374 | intros c st st'.
375 | split. apply ceval__ceval_step. apply ceval_step__ceval.
376 | Qed.
377 |
378 | (* ####################################################### *)
379 | (** * Determinism of Evaluation (Simpler Proof) *)
380 |
381 | (** Here's a slicker proof showing that the evaluation relation is
382 | deterministic, using the fact that the relational and step-indexed
383 | definition of evaluation are the same. *)
384 |
385 | Theorem ceval_deterministic' : forall c st st1 st2,
386 | c / st || st1 ->
387 | c / st || st2 ->
388 | st1 = st2.
389 | Proof.
390 | intros c st st1 st2 He1 He2.
391 | apply ceval__ceval_step in He1.
392 | apply ceval__ceval_step in He2.
393 | inversion He1 as [i1 E1].
394 | inversion He2 as [i2 E2].
395 | apply ceval_step_more with (i2 := i1 + i2) in E1.
396 | apply ceval_step_more with (i2 := i1 + i2) in E2.
397 | rewrite E1 in E2. inversion E2. reflexivity.
398 | omega. omega. Qed.
399 |
400 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
401 |
--------------------------------------------------------------------------------
/ImpParser.v:
--------------------------------------------------------------------------------
1 | (** * ImpParser: Lexing and Parsing in Coq *)
2 |
3 | (** The development of the [Imp] language in Imp.v completely ignores
4 | issues of concrete syntax -- how an ascii string that a programmer
5 | might write gets translated into the abstract syntax trees defined
6 | by the datatypes [aexp], [bexp], and [com]. In this file we
7 | illustrate how the rest of the story can be filled in by building
8 | a simple lexical analyzer and parser using Coq's functional
9 | programming facilities.
10 |
11 | This development is not intended to be understood in detail: the
12 | explanations are fairly terse and there are no exercises. The
13 | main point is simply to demonstrate that it can be done. You are
14 | invited to look through the code -- most of it is not very
15 | complicated, though the parser relies on some "monadic"
16 | programming idioms that may require a little work to make out --
17 | but most readers will probably want to just skip down to the
18 | Examples section at the very end to get the punchline. *)
19 |
20 | (* ####################################################### *)
21 | (** * Internals *)
22 |
23 | Require Import SfLib.
24 | Require Import Imp.
25 |
26 | Require Import String.
27 | Require Import Ascii.
28 |
29 | Open Scope list_scope.
30 |
31 | (* ####################################################### *)
32 | (** ** Lexical Analysis *)
33 |
34 | Definition isWhite (c : ascii) : bool :=
35 | let n := nat_of_ascii c in
36 | orb (orb (beq_nat n 32) (* space *)
37 | (beq_nat n 9)) (* tab *)
38 | (orb (beq_nat n 10) (* linefeed *)
39 | (beq_nat n 13)). (* Carriage return. *)
40 |
41 | Notation "x '<=?' y" := (ble_nat x y)
42 | (at level 70, no associativity) : nat_scope.
43 |
44 | Definition isLowerAlpha (c : ascii) : bool :=
45 | let n := nat_of_ascii c in
46 | andb (97 <=? n) (n <=? 122).
47 |
48 | Definition isAlpha (c : ascii) : bool :=
49 | let n := nat_of_ascii c in
50 | orb (andb (65 <=? n) (n <=? 90))
51 | (andb (97 <=? n) (n <=? 122)).
52 |
53 | Definition isDigit (c : ascii) : bool :=
54 | let n := nat_of_ascii c in
55 | andb (48 <=? n) (n <=? 57).
56 |
57 | Inductive chartype := white | alpha | digit | other.
58 |
59 | Definition classifyChar (c : ascii) : chartype :=
60 | if isWhite c then
61 | white
62 | else if isAlpha c then
63 | alpha
64 | else if isDigit c then
65 | digit
66 | else
67 | other.
68 |
69 | Fixpoint list_of_string (s : string) : list ascii :=
70 | match s with
71 | | EmptyString => []
72 | | String c s => c :: (list_of_string s)
73 | end.
74 |
75 | Fixpoint string_of_list (xs : list ascii) : string :=
76 | fold_right String EmptyString xs.
77 |
78 | Definition token := string.
79 |
80 | Fixpoint tokenize_helper (cls : chartype) (acc xs : list ascii)
81 | : list (list ascii) :=
82 | let tk := match acc with [] => [] | _::_ => [rev acc] end in
83 | match xs with
84 | | [] => tk
85 | | (x::xs') =>
86 | match cls, classifyChar x, x with
87 | | _, _, "(" => tk ++ ["("]::(tokenize_helper other [] xs')
88 | | _, _, ")" => tk ++ [")"]::(tokenize_helper other [] xs')
89 | | _, white, _ => tk ++ (tokenize_helper white [] xs')
90 | | alpha,alpha,x => tokenize_helper alpha (x::acc) xs'
91 | | digit,digit,x => tokenize_helper digit (x::acc) xs'
92 | | other,other,x => tokenize_helper other (x::acc) xs'
93 | | _,tp,x => tk ++ (tokenize_helper tp [x] xs')
94 | end
95 | end %char.
96 |
97 | Definition tokenize (s : string) : list string :=
98 | map string_of_list (tokenize_helper white [] (list_of_string s)).
99 |
100 | Example tokenize_ex1 :
101 | tokenize "abc12==3 223*(3+(a+c))" %string
102 | = ["abc"; "12"; "=="; "3"; "223";
103 | "*"; "("; "3"; "+"; "(";
104 | "a"; "+"; "c"; ")"; ")"]%string.
105 | Proof. reflexivity. Qed.
106 |
107 | (* ####################################################### *)
108 | (** ** Parsing *)
109 |
110 | (* ####################################################### *)
111 | (** *** Options with Errors *)
112 |
113 | (* An option with error messages. *)
114 | Inductive optionE (X:Type) : Type :=
115 | | SomeE : X -> optionE X
116 | | NoneE : string -> optionE X.
117 |
118 | Implicit Arguments SomeE [[X]].
119 | Implicit Arguments NoneE [[X]].
120 |
121 | (* Some syntactic sugar to make writing nested match-expressions on
122 | optionE more convenient. *)
123 |
124 | Notation "'DO' ( x , y ) <== e1 ; e2"
125 | := (match e1 with
126 | | SomeE (x,y) => e2
127 | | NoneE err => NoneE err
128 | end)
129 | (right associativity, at level 60).
130 |
131 | Notation "'DO' ( x , y ) <-- e1 ; e2 'OR' e3"
132 | := (match e1 with
133 | | SomeE (x,y) => e2
134 | | NoneE err => e3
135 | end)
136 | (right associativity, at level 60, e2 at next level).
137 |
138 | (* ####################################################### *)
139 | (** *** Symbol Table *)
140 |
141 | (* Build a mapping from [tokens] to [nats]. A real parser would do
142 | this incrementally as it encountered new symbols, but passing
143 | around the symbol table inside the parsing functions is a bit
144 | inconvenient, so instead we do it as a first pass. *)
145 | Fixpoint build_symtable (xs : list token) (n : nat) : (token -> nat) :=
146 | match xs with
147 | | [] => (fun s => n)
148 | | x::xs =>
149 | if (forallb isLowerAlpha (list_of_string x))
150 | then (fun s => if string_dec s x then n else (build_symtable xs (S n) s))
151 | else build_symtable xs n
152 | end.
153 |
154 | (* ####################################################### *)
155 | (** *** Generic Combinators for Building Parsers *)
156 |
157 | Open Scope string_scope.
158 |
159 | Definition parser (T : Type) :=
160 | list token -> optionE (T * list token).
161 |
162 | Fixpoint many_helper {T} (p : parser T) acc steps xs :=
163 | match steps, p xs with
164 | | 0, _ => NoneE "Too many recursive calls"
165 | | _, NoneE _ => SomeE ((rev acc), xs)
166 | | S steps', SomeE (t, xs') => many_helper p (t::acc) steps' xs'
167 | end.
168 |
169 | (* A (step-indexed) parser which expects zero or more [p]s *)
170 | Fixpoint many {T} (p : parser T) (steps : nat) : parser (list T) :=
171 | many_helper p [] steps.
172 |
173 | (* A parser which expects a given token, followed by p *)
174 | Definition firstExpect {T} (t : token) (p : parser T) : parser T :=
175 | fun xs => match xs with
176 | | x::xs' => if string_dec x t
177 | then p xs'
178 | else NoneE ("expected '" ++ t ++ "'.")
179 | | [] => NoneE ("expected '" ++ t ++ "'.")
180 | end.
181 |
182 | (* A parser which expects a particular token *)
183 | Definition expect (t : token) : parser unit :=
184 | firstExpect t (fun xs => SomeE(tt, xs)).
185 |
186 | (* ####################################################### *)
187 | (** *** A Recursive-Descent Parser for Imp *)
188 |
189 | (* Identifiers *)
190 | Definition parseIdentifier (symtable :string->nat) (xs : list token)
191 | : optionE (id * list token) :=
192 | match xs with
193 | | [] => NoneE "Expected identifier"
194 | | x::xs' =>
195 | if forallb isLowerAlpha (list_of_string x) then
196 | SomeE (Id (symtable x), xs')
197 | else
198 | NoneE ("Illegal identifier:'" ++ x ++ "'")
199 | end.
200 |
201 | (* Numbers *)
202 | Definition parseNumber (xs : list token) : optionE (nat * list token) :=
203 | match xs with
204 | | [] => NoneE "Expected number"
205 | | x::xs' =>
206 | if forallb isDigit (list_of_string x) then
207 | SomeE (fold_left (fun n d =>
208 | 10 * n + (nat_of_ascii d - nat_of_ascii "0"%char))
209 | (list_of_string x)
210 | 0,
211 | xs')
212 | else
213 | NoneE "Expected number"
214 | end.
215 |
216 | (* Parse arithmetic expressions *)
217 | Fixpoint parsePrimaryExp (steps:nat) symtable (xs : list token)
218 | : optionE (aexp * list token) :=
219 | match steps with
220 | | 0 => NoneE "Too many recursive calls"
221 | | S steps' =>
222 | DO (i, rest) <-- parseIdentifier symtable xs ;
223 | SomeE (AId i, rest)
224 | OR DO (n, rest) <-- parseNumber xs ;
225 | SomeE (ANum n, rest)
226 | OR (DO (e, rest) <== firstExpect "(" (parseSumExp steps' symtable) xs;
227 | DO (u, rest') <== expect ")" rest ;
228 | SomeE(e,rest'))
229 | end
230 | with parseProductExp (steps:nat) symtable (xs : list token) :=
231 | match steps with
232 | | 0 => NoneE "Too many recursive calls"
233 | | S steps' =>
234 | DO (e, rest) <==
235 | parsePrimaryExp steps' symtable xs ;
236 | DO (es, rest') <==
237 | many (firstExpect "*" (parsePrimaryExp steps' symtable)) steps' rest;
238 | SomeE (fold_left AMult es e, rest')
239 | end
240 | with parseSumExp (steps:nat) symtable (xs : list token) :=
241 | match steps with
242 | | 0 => NoneE "Too many recursive calls"
243 | | S steps' =>
244 | DO (e, rest) <==
245 | parseProductExp steps' symtable xs ;
246 | DO (es, rest') <==
247 | many (fun xs =>
248 | DO (e,rest') <--
249 | firstExpect "+" (parseProductExp steps' symtable) xs;
250 | SomeE ( (true, e), rest')
251 | OR DO (e,rest') <==
252 | firstExpect "-" (parseProductExp steps' symtable) xs;
253 | SomeE ( (false, e), rest'))
254 | steps' rest;
255 | SomeE (fold_left (fun e0 term =>
256 | match term with
257 | (true, e) => APlus e0 e
258 | | (false, e) => AMinus e0 e
259 | end)
260 | es e,
261 | rest')
262 | end.
263 |
264 | Definition parseAExp := parseSumExp.
265 |
266 | (* Parsing boolean expressions. *)
267 | Fixpoint parseAtomicExp (steps:nat) (symtable : string->nat) (xs : list token) :=
268 | match steps with
269 | | 0 => NoneE "Too many recursive calls"
270 | | S steps' =>
271 | DO (u,rest) <-- expect "true" xs;
272 | SomeE (BTrue,rest)
273 | OR DO (u,rest) <-- expect "false" xs;
274 | SomeE (BFalse,rest)
275 | OR DO (e,rest) <-- firstExpect "not" (parseAtomicExp steps' symtable) xs;
276 | SomeE (BNot e, rest)
277 | OR DO (e,rest) <-- firstExpect "(" (parseConjunctionExp steps' symtable) xs;
278 | (DO (u,rest') <== expect ")" rest; SomeE (e, rest'))
279 | OR DO (e, rest) <== parseProductExp steps' symtable xs ;
280 | (DO (e', rest') <--
281 | firstExpect "==" (parseAExp steps' symtable) rest ;
282 | SomeE (BEq e e', rest')
283 | OR DO (e', rest') <--
284 | firstExpect "<=" (parseAExp steps' symtable) rest ;
285 | SomeE (BLe e e', rest')
286 | OR
287 | NoneE "Expected '==' or '<=' after arithmetic expression")
288 | end
289 | with parseConjunctionExp (steps:nat) (symtable : string->nat) (xs : list token) :=
290 | match steps with
291 | | 0 => NoneE "Too many recursive calls"
292 | | S steps' =>
293 | DO (e, rest) <==
294 | parseAtomicExp steps' symtable xs ;
295 | DO (es, rest') <==
296 | many (firstExpect "&&" (parseAtomicExp steps' symtable)) steps' rest;
297 | SomeE (fold_left BAnd es e, rest')
298 | end.
299 |
300 | Definition parseBExp := parseConjunctionExp.
301 |
302 | (*
303 | Eval compute in
304 | (parseProductExp 100 (tokenize "x*y*(x*x)*x")).
305 |
306 | Eval compute in
307 | (parseDisjunctionExp 100 (tokenize "not((x==x||x*x<=(x*x)*x)&&x==x)")).
308 | *)
309 |
310 | (* Parsing commands *)
311 | Fixpoint parseSimpleCommand (steps:nat) (symtable:string->nat) (xs : list token) :=
312 | match steps with
313 | | 0 => NoneE "Too many recursive calls"
314 | | S steps' =>
315 | DO (u, rest) <-- expect "SKIP" xs;
316 | SomeE (SKIP, rest)
317 | OR DO (e,rest) <--
318 | firstExpect "IF" (parseBExp steps' symtable) xs;
319 | DO (c,rest') <==
320 | firstExpect "THEN" (parseSequencedCommand steps' symtable) rest;
321 | DO (c',rest'') <==
322 | firstExpect "ELSE" (parseSequencedCommand steps' symtable) rest';
323 | DO (u,rest''') <==
324 | expect "END" rest'';
325 | SomeE(IFB e THEN c ELSE c' FI, rest''')
326 | OR DO (e,rest) <--
327 | firstExpect "WHILE" (parseBExp steps' symtable) xs;
328 | DO (c,rest') <==
329 | firstExpect "DO" (parseSequencedCommand steps' symtable) rest;
330 | DO (u,rest'') <==
331 | expect "END" rest';
332 | SomeE(WHILE e DO c END, rest'')
333 | OR DO (i, rest) <==
334 | parseIdentifier symtable xs;
335 | DO (e, rest') <==
336 | firstExpect ":=" (parseAExp steps' symtable) rest;
337 | SomeE(i ::= e, rest')
338 | end
339 |
340 | with parseSequencedCommand (steps:nat) (symtable:string->nat) (xs : list token) :=
341 | match steps with
342 | | 0 => NoneE "Too many recursive calls"
343 | | S steps' =>
344 | DO (c, rest) <==
345 | parseSimpleCommand steps' symtable xs;
346 | DO (c', rest') <--
347 | firstExpect ";;" (parseSequencedCommand steps' symtable) rest;
348 | SomeE(c ;; c', rest')
349 | OR
350 | SomeE(c, rest)
351 | end.
352 |
353 | Definition bignumber := 1000.
354 |
355 | Definition parse (str : string) : optionE (com * list token) :=
356 | let tokens := tokenize str in
357 | parseSequencedCommand bignumber (build_symtable tokens 0) tokens.
358 |
359 | (* ####################################################### *)
360 | (** * Examples *)
361 |
362 |
363 |
364 | Eval compute in parse "
365 | IF x == y + 1 + 2 - y * 6 + 3 THEN
366 | x := x * 1;;
367 | y := 0
368 | ELSE
369 | SKIP
370 | END ".
371 | (* ====> *)
372 | (* SomeE *)
373 | (* (IFB BEq (AId (Id 0)) *)
374 | (* (APlus *)
375 | (* (AMinus (APlus (APlus (AId (Id 1)) (ANum 1)) (ANum 2)) *)
376 | (* (AMult (AId (Id 1)) (ANum 6))) *)
377 | (* (ANum 3)) *)
378 | (* THEN Id 0 ::= AMult (AId (Id 0)) (ANum 1);; Id 1 ::= ANum 0 *)
379 | (* ELSE SKIP FI, []) *)
380 |
381 |
382 | Eval compute in parse "
383 | SKIP;;
384 | z:=x*y*(x*x);;
385 | WHILE x==x DO
386 | IF z <= z*z && not x == 2 THEN
387 | x := z;;
388 | y := z
389 | ELSE
390 | SKIP
391 | END;;
392 | SKIP
393 | END;;
394 | x:=z ".
395 | (* ====> *)
396 | (* SomeE *)
397 | (* (SKIP;; *)
398 | (* Id 0 ::= AMult (AMult (AId (Id 1)) (AId (Id 2))) *)
399 | (* (AMult (AId (Id 1)) (AId (Id 1)));; *)
400 | (* WHILE BEq (AId (Id 1)) (AId (Id 1)) DO *)
401 | (* IFB BAnd (BLe (AId (Id 0)) (AMult (AId (Id 0)) (AId (Id 0)))) *)
402 | (* (BNot (BEq (AId (Id 1)) (ANum 2))) *)
403 | (* THEN Id 1 ::= AId (Id 0);; Id 2 ::= AId (Id 0) *)
404 | (* ELSE SKIP FI;; *)
405 | (* SKIP *)
406 | (* END;; *)
407 | (* Id 1 ::= AId (Id 0), *)
408 | (* []) *)
409 |
410 |
411 | Eval compute in parse "
412 | SKIP;;
413 | z:=x*y*(x*x);;
414 | WHILE x==x DO
415 | IF z <= z*z && not x == 2 THEN
416 | x := z;;
417 | y := z
418 | ELSE
419 | SKIP
420 | END;;
421 | SKIP
422 | END;;
423 | x:=z ".
424 | (* =====> *)
425 | (* SomeE *)
426 | (* (SKIP;; *)
427 | (* Id 0 ::= AMult (AMult (AId (Id 1)) (AId (Id 2))) *)
428 | (* (AMult (AId (Id 1)) (AId (Id 1)));; *)
429 | (* WHILE BEq (AId (Id 1)) (AId (Id 1)) DO *)
430 | (* IFB BAnd (BLe (AId (Id 0)) (AMult (AId (Id 0)) (AId (Id 0)))) *)
431 | (* (BNot (BEq (AId (Id 1)) (ANum 2))) *)
432 | (* THEN Id 1 ::= AId (Id 0);; *)
433 | (* Id 2 ::= AId (Id 0) *)
434 | (* ELSE SKIP *)
435 | (* FI;; *)
436 | (* SKIP *)
437 | (* END;; *)
438 | (* Id 1 ::= AId (Id 0), *)
439 | (* []). *)
440 |
441 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
442 |
--------------------------------------------------------------------------------
/Logic.v:
--------------------------------------------------------------------------------
1 | (** * Logic: Logic in Coq *)
2 |
3 | Require Export MoreCoq.
4 |
5 |
6 |
7 | (** Coq's built-in logic is very small: the only primitives are
8 | [Inductive] definitions, universal quantification ([forall]), and
9 | implication ([->]), while all the other familiar logical
10 | connectives -- conjunction, disjunction, negation, existential
11 | quantification, even equality -- can be encoded using just these.
12 |
13 | This chapter explains the encodings and shows how the tactics
14 | we've seen can be used to carry out standard forms of logical
15 | reasoning involving these connectives.
16 |
17 | *)
18 |
19 | (* ########################################################### *)
20 | (** * Propositions *)
21 |
22 | (** In previous chapters, we have seen many examples of factual
23 | claims (_propositions_) and ways of presenting evidence of their
24 | truth (_proofs_). In particular, we have worked extensively with
25 | _equality propositions_ of the form [e1 = e2], with
26 | implications ([P -> Q]), and with quantified propositions
27 | ([forall x, P]).
28 | *)
29 |
30 |
31 | (** In Coq, the type of things that can (potentially)
32 | be proven is [Prop]. *)
33 |
34 | (** Here is an example of a provable proposition: *)
35 |
36 | Check (3 = 3).
37 | (* ===> Prop *)
38 |
39 | (** Here is an example of an unprovable proposition: *)
40 |
41 | Check (forall (n:nat), n = 2).
42 | (* ===> Prop *)
43 |
44 | (** Recall that [Check] asks Coq to tell us the type of the indicated
45 | expression. *)
46 |
47 | (* ########################################################### *)
48 | (** * Proofs and Evidence *)
49 |
50 | (** In Coq, propositions have the same status as other types, such as
51 | [nat]. Just as the natural numbers [0], [1], [2], etc. inhabit
52 | the type [nat], a Coq proposition [P] is inhabited by its
53 | _proofs_. We will refer to such inhabitants as _proof term_ or
54 | _proof object_ or _evidence_ for the truth of [P].
55 |
56 | In Coq, when we state and then prove a lemma such as:
57 |
58 | Lemma silly : 0 * 3 = 0.
59 | Proof. reflexivity. Qed.
60 |
61 | the tactics we use within the [Proof]...[Qed] keywords tell Coq
62 | how to construct a proof term that inhabits the proposition. In
63 | this case, the proposition [0 * 3 = 0] is justified by a
64 | combination of the _definition_ of [mult], which says that [0 * 3]
65 | _simplifies_ to just [0], and the _reflexive_ principle of
66 | equality, which says that [0 = 0].
67 |
68 |
69 | *)
70 |
71 | (** *** *)
72 |
73 | Lemma silly : 0 * 3 = 0.
74 | Proof. reflexivity. Qed.
75 |
76 | (** We can see which proof term Coq constructs for a given Lemma by
77 | using the [Print] directive: *)
78 |
79 | Print silly.
80 | (* ===> silly = eq_refl : 0 * 3 = 0 *)
81 |
82 | (** Here, the [eq_refl] proof term witnesses the equality. (More on
83 | equality later!)*)
84 |
85 | (** ** Implications _are_ functions *)
86 |
87 | (** Just as we can implement natural number multiplication as a
88 | function:
89 |
90 | [
91 | mult : nat -> nat -> nat
92 | ]
93 |
94 | The _proof term_ for an implication [P -> Q] is a _function_ that
95 | takes evidence for [P] as input and produces evidence for [Q] as its
96 | output.
97 | *)
98 |
99 | Lemma silly_implication : (1 + 1) = 2 -> 0 * 3 = 0.
100 | Proof. intros H. reflexivity. Qed.
101 |
102 | (** We can see that the proof term for the above lemma is indeed a
103 | function: *)
104 |
105 | Print silly_implication.
106 | (* ===> silly_implication = fun _ : 1 + 1 = 2 => eq_refl
107 | : 1 + 1 = 2 -> 0 * 3 = 0 *)
108 |
109 | (** ** Defining propositions *)
110 |
111 | (** Just as we can create user-defined inductive types (like the
112 | lists, binary representations of natural numbers, etc., that we
113 | seen before), we can also create _user-defined_ propositions.
114 |
115 | Question: How do you define the meaning of a proposition?
116 | *)
117 |
118 | (** *** *)
119 |
120 | (** The meaning of a proposition is given by _rules_ and _definitions_
121 | that say how to construct _evidence_ for the truth of the
122 | proposition from other evidence.
123 |
124 | - Typically, rules are defined _inductively_, just like any other
125 | datatype.
126 |
127 | - Sometimes a proposition is declared to be true without
128 | substantiating evidence. Such propositions are called _axioms_.
129 |
130 | In this, and subsequence chapters, we'll see more about how these
131 | proof terms work in more detail.
132 | *)
133 |
134 | (* ########################################################### *)
135 | (** * Conjunction (Logical "and") *)
136 |
137 | (** The logical conjunction of propositions [P] and [Q] can be
138 | represented using an [Inductive] definition with one
139 | constructor. *)
140 |
141 | Inductive and (P Q : Prop) : Prop :=
142 | conj : P -> Q -> (and P Q).
143 |
144 | (** The intuition behind this definition is simple: to
145 | construct evidence for [and P Q], we must provide evidence
146 | for [P] and evidence for [Q]. More precisely:
147 |
148 | - [conj p q] can be taken as evidence for [and P Q] if [p]
149 | is evidence for [P] and [q] is evidence for [Q]; and
150 |
151 | - this is the _only_ way to give evidence for [and P Q] --
152 | that is, if someone gives us evidence for [and P Q], we
153 | know it must have the form [conj p q], where [p] is
154 | evidence for [P] and [q] is evidence for [Q].
155 |
156 | Since we'll be using conjunction a lot, let's introduce a more
157 | familiar-looking infix notation for it. *)
158 |
159 | Notation "P /\ Q" := (and P Q) : type_scope.
160 |
161 | (** (The [type_scope] annotation tells Coq that this notation
162 | will be appearing in propositions, not values.) *)
163 |
164 | (** Consider the "type" of the constructor [conj]: *)
165 |
166 | Check conj.
167 | (* ===> forall P Q : Prop, P -> Q -> P /\ Q *)
168 |
169 | (** Notice that it takes 4 inputs -- namely the propositions [P]
170 | and [Q] and evidence for [P] and [Q] -- and returns as output the
171 | evidence of [P /\ Q]. *)
172 |
173 | (** ** "Introducing" conjunctions *)
174 | (** Besides the elegance of building everything up from a tiny
175 | foundation, what's nice about defining conjunction this way is
176 | that we can prove statements involving conjunction using the
177 | tactics that we already know. For example, if the goal statement
178 | is a conjuction, we can prove it by applying the single
179 | constructor [conj], which (as can be seen from the type of [conj])
180 | solves the current goal and leaves the two parts of the
181 | conjunction as subgoals to be proved separately. *)
182 |
183 | Theorem and_example :
184 | (0 = 0) /\ (4 = mult 2 2).
185 | Proof.
186 | apply conj.
187 | Case "left". reflexivity.
188 | Case "right". reflexivity. Qed.
189 |
190 | (** Just for convenience, we can use the tactic [split] as a shorthand for
191 | [apply conj]. *)
192 |
193 | Theorem and_example' :
194 | (0 = 0) /\ (4 = mult 2 2).
195 | Proof.
196 | split.
197 | Case "left". reflexivity.
198 | Case "right". reflexivity. Qed.
199 |
200 | (** ** "Eliminating" conjunctions *)
201 | (** Conversely, the [destruct] tactic can be used to take a
202 | conjunction hypothesis in the context, calculate what evidence
203 | must have been used to build it, and add variables representing
204 | this evidence to the proof context. *)
205 |
206 | Theorem proj1 : forall P Q : Prop,
207 | P /\ Q -> P.
208 | Proof.
209 | intros P Q H.
210 | destruct H as [HP HQ].
211 | apply HP. Qed.
212 |
213 | (** **** Exercise: 1 star, optional (proj2) *)
214 | Theorem proj2 : forall P Q : Prop,
215 | P /\ Q -> Q.
216 | Proof.
217 | intros P Q H.
218 | destruct H.
219 | apply H0.
220 | Qed.
221 | (** [] *)
222 |
223 | Theorem and_commut : forall P Q : Prop,
224 | P /\ Q -> Q /\ P.
225 | Proof.
226 | (* WORKED IN CLASS *)
227 | intros P Q H.
228 | destruct H as [HP HQ].
229 | split.
230 | Case "left". apply HQ.
231 | Case "right". apply HP. Qed.
232 |
233 |
234 | (** **** Exercise: 2 stars (and_assoc) *)
235 | (** In the following proof, notice how the _nested pattern_ in the
236 | [destruct] breaks the hypothesis [H : P /\ (Q /\ R)] down into
237 | [HP: P], [HQ : Q], and [HR : R]. Finish the proof from there: *)
238 |
239 | Theorem and_assoc : forall P Q R : Prop,
240 | P /\ (Q /\ R) -> (P /\ Q) /\ R.
241 | Proof.
242 | intros P Q R H.
243 | destruct H as [HP [HQ HR]].
244 | split. split. apply HP.
245 | apply HQ. apply HR.
246 | Qed.
247 | (** [] *)
248 |
249 |
250 |
251 | (* ###################################################### *)
252 | (** * Iff *)
253 |
254 | (** The handy "if and only if" connective is just the conjunction of
255 | two implications. *)
256 |
257 | Definition iff (P Q : Prop) := (P -> Q) /\ (Q -> P).
258 |
259 | Notation "P <-> Q" := (iff P Q)
260 | (at level 95, no associativity)
261 | : type_scope.
262 |
263 | Theorem iff_implies : forall P Q : Prop,
264 | (P <-> Q) -> P -> Q.
265 | Proof.
266 | intros P Q H.
267 | destruct H as [HAB HBA]. apply HAB. Qed.
268 |
269 | Theorem iff_sym : forall P Q : Prop,
270 | (P <-> Q) -> (Q <-> P).
271 | Proof.
272 | (* WORKED IN CLASS *)
273 | intros P Q H.
274 | destruct H as [HAB HBA].
275 | split.
276 | Case "->". apply HBA.
277 | Case "<-". apply HAB. Qed.
278 |
279 | (** **** Exercise: 1 star, optional (iff_properties) *)
280 | (** Using the above proof that [<->] is symmetric ([iff_sym]) as
281 | a guide, prove that it is also reflexive and transitive. *)
282 |
283 | Theorem iff_refl : forall P : Prop,
284 | P <-> P.
285 | Proof.
286 | intros P.
287 | split. intros H. apply H.
288 | intros H. apply H.
289 | Qed.
290 |
291 | Theorem iff_trans : forall P Q R : Prop,
292 | (P <-> Q) -> (Q <-> R) -> (P <-> R).
293 | Proof.
294 | intros P Q R H1 H2.
295 | destruct H1. destruct H2.
296 | split. intros Hp. apply H in Hp. apply H1 in Hp.
297 | apply Hp.
298 | intros Hr. apply H2 in Hr. apply H0 in Hr. apply Hr.
299 | Qed.
300 |
301 |
302 | (** Hint: If you have an iff hypothesis in the context, you can use
303 | [inversion] to break it into two separate implications. (Think
304 | about why this works.) *)
305 | (** [] *)
306 |
307 |
308 |
309 | (** Some of Coq's tactics treat [iff] statements specially, thus
310 | avoiding the need for some low-level manipulation when reasoning
311 | with them. In particular, [rewrite] can be used with [iff]
312 | statements, not just equalities. *)
313 |
314 | (* ############################################################ *)
315 | (** * Disjunction (Logical "or") *)
316 |
317 | (** ** Implementing disjunction *)
318 |
319 | (** Disjunction ("logical or") can also be defined as an
320 | inductive proposition. *)
321 |
322 | Inductive or (P Q : Prop) : Prop :=
323 | | or_introl : P -> or P Q
324 | | or_intror : Q -> or P Q.
325 |
326 | Notation "P \/ Q" := (or P Q) : type_scope.
327 |
328 | (** Consider the "type" of the constructor [or_introl]: *)
329 |
330 | Check or_introl.
331 | (* ===> forall P Q : Prop, P -> P \/ Q *)
332 |
333 | (** It takes 3 inputs, namely the propositions [P], [Q] and
334 | evidence of [P], and returns, as output, the evidence of [P \/ Q].
335 | Next, look at the type of [or_intror]: *)
336 |
337 | Check or_intror.
338 | (* ===> forall P Q : Prop, Q -> P \/ Q *)
339 |
340 | (** It is like [or_introl] but it requires evidence of [Q]
341 | instead of evidence of [P]. *)
342 |
343 | (** Intuitively, there are two ways of giving evidence for [P \/ Q]:
344 |
345 | - give evidence for [P] (and say that it is [P] you are giving
346 | evidence for -- this is the function of the [or_introl]
347 | constructor), or
348 |
349 | - give evidence for [Q], tagged with the [or_intror]
350 | constructor. *)
351 |
352 | (** *** *)
353 | (** Since [P \/ Q] has two constructors, doing [destruct] on a
354 | hypothesis of type [P \/ Q] yields two subgoals. *)
355 |
356 | Theorem or_commut : forall P Q : Prop,
357 | P \/ Q -> Q \/ P.
358 | Proof.
359 | intros P Q H.
360 | destruct H as [HP | HQ].
361 | Case "left". apply or_intror. apply HP.
362 | Case "right". apply or_introl. apply HQ. Qed.
363 |
364 | (** From here on, we'll use the shorthand tactics [left] and [right]
365 | in place of [apply or_introl] and [apply or_intror]. *)
366 |
367 | Theorem or_commut' : forall P Q : Prop,
368 | P \/ Q -> Q \/ P.
369 | Proof.
370 | intros P Q H.
371 | destruct H as [HP | HQ].
372 | Case "left". right. apply HP.
373 | Case "right". left. apply HQ. Qed.
374 |
375 |
376 |
377 |
378 |
379 | Theorem or_distributes_over_and_1 : forall P Q R : Prop,
380 | P \/ (Q /\ R) -> (P \/ Q) /\ (P \/ R).
381 | Proof.
382 | intros P Q R. intros H. destruct H as [HP | [HQ HR]].
383 | Case "left". split.
384 | SCase "left". left. apply HP.
385 | SCase "right". left. apply HP.
386 | Case "right". split.
387 | SCase "left". right. apply HQ.
388 | SCase "right". right. apply HR. Qed.
389 |
390 | (** **** Exercise: 2 stars (or_distributes_over_and_2) *)
391 | Theorem or_distributes_over_and_2 : forall P Q R : Prop,
392 | (P \/ Q) /\ (P \/ R) -> P \/ (Q /\ R).
393 | Proof.
394 | intros P Q R H.
395 | destruct H. destruct H. left. apply H.
396 | destruct H0. left. apply H0. right. split. apply H.
397 | apply H0.
398 | Qed.
399 | (** [] *)
400 |
401 | (** **** Exercise: 1 star, optional (or_distributes_over_and) *)
402 | Theorem or_distributes_over_and : forall P Q R : Prop,
403 | P \/ (Q /\ R) <-> (P \/ Q) /\ (P \/ R).
404 | Proof.
405 | intros P Q R.
406 | split. apply or_distributes_over_and_1.
407 | apply or_distributes_over_and_2.
408 | Qed.
409 | (** [] *)
410 |
411 | (* ################################################### *)
412 | (** ** Relating [/\] and [\/] with [andb] and [orb] *)
413 |
414 | (** We've already seen several places where analogous structures
415 | can be found in Coq's computational ([Type]) and logical ([Prop])
416 | worlds. Here is one more: the boolean operators [andb] and [orb]
417 | are clearly analogs of the logical connectives [/\] and [\/].
418 | This analogy can be made more precise by the following theorems,
419 | which show how to translate knowledge about [andb] and [orb]'s
420 | behaviors on certain inputs into propositional facts about those
421 | inputs. *)
422 |
423 | Theorem andb_prop : forall b c,
424 | andb b c = true -> b = true /\ c = true.
425 | Proof.
426 | (* WORKED IN CLASS *)
427 | intros b c H.
428 | destruct b.
429 | Case "b = true". destruct c.
430 | SCase "c = true". apply conj. reflexivity. reflexivity.
431 | SCase "c = false". inversion H.
432 | Case "b = false". inversion H. Qed.
433 |
434 | Theorem andb_true_intro : forall b c,
435 | b = true /\ c = true -> andb b c = true.
436 | Proof.
437 | (* WORKED IN CLASS *)
438 | intros b c H.
439 | destruct H.
440 | rewrite H. rewrite H0. reflexivity. Qed.
441 |
442 | (** **** Exercise: 2 stars, optional (andb_false) *)
443 | Theorem andb_false : forall b c,
444 | andb b c = false -> b = false \/ c = false.
445 | Proof.
446 | intros b c H.
447 | destruct b. destruct c. inversion H.
448 | right. reflexivity. left. reflexivity.
449 | Qed.
450 |
451 | (** **** Exercise: 2 stars, optional (orb_false) *)
452 | Theorem orb_prop : forall b c,
453 | orb b c = true -> b = true \/ c = true.
454 | Proof.
455 | intros b c H.
456 | destruct b.
457 | left. reflexivity.
458 | destruct c. right. reflexivity.
459 | inversion H.
460 | Qed.
461 |
462 | (** **** Exercise: 2 stars, optional (orb_false_elim) *)
463 | Theorem orb_false_elim : forall b c,
464 | orb b c = false -> b = false /\ c = false.
465 | Proof.
466 | intros b c H.
467 | destruct b. inversion H.
468 | destruct c. inversion H.
469 | split. reflexivity. reflexivity.
470 | Qed.
471 | (** [] *)
472 |
473 |
474 |
475 | (* ################################################### *)
476 | (** * Falsehood *)
477 |
478 | (** Logical falsehood can be represented in Coq as an inductively
479 | defined proposition with no constructors. *)
480 |
481 | Inductive False : Prop := .
482 |
483 | (** Intuition: [False] is a proposition for which there is no way
484 | to give evidence. *)
485 |
486 |
487 | (** Since [False] has no constructors, inverting an assumption
488 | of type [False] always yields zero subgoals, allowing us to
489 | immediately prove any goal. *)
490 |
491 | Theorem False_implies_nonsense :
492 | False -> 2 + 2 = 5.
493 | Proof.
494 | intros contra.
495 | inversion contra. Qed.
496 |
497 | (** How does this work? The [inversion] tactic breaks [contra] into
498 | each of its possible cases, and yields a subgoal for each case.
499 | As [contra] is evidence for [False], it has _no_ possible cases,
500 | hence, there are no possible subgoals and the proof is done. *)
501 |
502 | (** *** *)
503 | (** Conversely, the only way to prove [False] is if there is already
504 | something nonsensical or contradictory in the context: *)
505 |
506 | Theorem nonsense_implies_False :
507 | 2 + 2 = 5 -> False.
508 | Proof.
509 | intros contra.
510 | inversion contra. Qed.
511 |
512 | (** Actually, since the proof of [False_implies_nonsense]
513 | doesn't actually have anything to do with the specific nonsensical
514 | thing being proved; it can easily be generalized to work for an
515 | arbitrary [P]: *)
516 |
517 | Theorem ex_falso_quodlibet : forall (P:Prop),
518 | False -> P.
519 | Proof.
520 | (* WORKED IN CLASS *)
521 | intros P contra.
522 | inversion contra. Qed.
523 |
524 | (** The Latin _ex falso quodlibet_ means, literally, "from
525 | falsehood follows whatever you please." This theorem is also
526 | known as the _principle of explosion_. *)
527 |
528 |
529 | (* #################################################### *)
530 | (** ** Truth *)
531 |
532 | (** Since we have defined falsehood in Coq, one might wonder whether
533 | it is possible to define truth in the same way. We can. *)
534 |
535 | (** **** Exercise: 2 stars, advanced (True) *)
536 | (** Define [True] as another inductively defined proposition. (The
537 | intution is that [True] should be a proposition for which it is
538 | trivial to give evidence.) *)
539 |
540 | Inductive True : Prop := I : True.
541 |
542 | (** [] *)
543 |
544 | (** However, unlike [False], which we'll use extensively, [True] is
545 | used fairly rarely. By itself, it is trivial (and therefore
546 | uninteresting) to prove as a goal, and it carries no useful
547 | information as a hypothesis. But it can be useful when defining
548 | complex [Prop]s using conditionals, or as a parameter to
549 | higher-order [Prop]s. *)
550 |
551 | (* #################################################### *)
552 | (** * Negation *)
553 |
554 | (** The logical complement of a proposition [P] is written [not
555 | P] or, for shorthand, [~P]: *)
556 |
557 | Definition not (P:Prop) := P -> False.
558 |
559 | (** The intuition is that, if [P] is not true, then anything at
560 | all (even [False]) follows from assuming [P]. *)
561 |
562 | Notation "~ x" := (not x) : type_scope.
563 |
564 | Check not.
565 | (* ===> Prop -> Prop *)
566 |
567 | (** It takes a little practice to get used to working with
568 | negation in Coq. Even though you can see perfectly well why
569 | something is true, it can be a little hard at first to get things
570 | into the right configuration so that Coq can see it! Here are
571 | proofs of a few familiar facts about negation to get you warmed
572 | up. *)
573 |
574 | Theorem not_False :
575 | ~ False.
576 | Proof.
577 | unfold not. intros H. inversion H. Qed.
578 |
579 | (** *** *)
580 | Theorem contradiction_implies_anything : forall P Q : Prop,
581 | (P /\ ~P) -> Q.
582 | Proof.
583 | (* WORKED IN CLASS *)
584 | intros P Q H. destruct H as [HP HNA]. unfold not in HNA.
585 | apply HNA in HP. inversion HP. Qed.
586 |
587 | Theorem double_neg : forall P : Prop,
588 | P -> ~~P.
589 | Proof.
590 | (* WORKED IN CLASS *)
591 | intros P H. unfold not. intros G. apply G. apply H. Qed.
592 |
593 | (** **** Exercise: 2 stars, advanced (double_neg_inf) *)
594 | (** Write an informal proof of [double_neg]:
595 |
596 | _Theorem_: [P] implies [~~P], for any proposition [P].
597 |
598 | _Proof_:
599 | ...
600 | []
601 | *)
602 |
603 | (** **** Exercise: 2 stars (contrapositive) *)
604 | Theorem contrapositive : forall P Q : Prop,
605 | (P -> Q) -> (~Q -> ~P).
606 | Proof.
607 | intros P Q H.
608 | unfold not.
609 | intros H1 H2.
610 | apply H in H2. apply H1 in H2.
611 | apply H2.
612 | Qed.
613 | (** [] *)
614 |
615 | (** **** Exercise: 1 star (not_both_true_and_false) *)
616 | Theorem not_both_true_and_false : forall P : Prop,
617 | ~ (P /\ ~P).
618 | Proof.
619 | intros P.
620 | unfold not.
621 | intros H.
622 | destruct H. apply H0 in H. apply H.
623 | Qed.
624 | (** [] *)
625 |
626 | (** **** Exercise: 1 star, advanced (informal_not_PNP) *)
627 | (** Write an informal proof (in English) of the proposition [forall P
628 | : Prop, ~(P /\ ~P)]. *)
629 |
630 | (* ... *)
631 | (** [] *)
632 |
633 | (** *** Constructive logic *)
634 | (** Note that some theorems that are true in classical logic are _not_
635 | provable in Coq's (constructive) logic. E.g., let's look at how
636 | this proof gets stuck... *)
637 |
638 | Theorem classic_double_neg : forall P : Prop,
639 | ~ ~ P -> P.
640 | Proof.
641 | (* WORKED IN CLASS *)
642 | intros P H. unfold not in H.
643 | (* But now what? There is no way to "invent" evidence for [~P]
644 | from evidence for [P]. *)
645 | Abort.
646 |
647 | (** **** Exercise: 5 stars, advanced, optional (classical_axioms) *)
648 | (** For those who like a challenge, here is an exercise
649 | taken from the Coq'Art book (p. 123). The following five
650 | statements are often considered as characterizations of
651 | classical logic (as opposed to constructive logic, which is
652 | what is "built in" to Coq). We can't prove them in Coq, but
653 | we can consistently add any one of them as an unproven axiom
654 | if we wish to work in classical logic. Prove that these five
655 | propositions are equivalent. *)
656 |
657 | Definition peirce := forall P Q: Prop,
658 | ((P->Q)->P)->P.
659 | Definition classic := forall P:Prop,
660 | ~~P -> P.
661 | Definition excluded_middle := forall P:Prop,
662 | P \/ ~P.
663 | Definition de_morgan_not_and_not := forall P Q:Prop,
664 | ~(~P /\ ~Q) -> P\/Q.
665 | Definition implies_to_or := forall P Q:Prop,
666 | (P->Q) -> (~P\/Q).
667 |
668 | Theorem equivalent_comm : forall P Q R: Prop,
669 | (P <-> Q) -> (Q <-> R) -> (P <-> R).
670 | Proof.
671 | intros.
672 | split. destruct H. destruct H0.
673 | intros. apply H in H3. apply H0 in H3. apply H3.
674 | intros. destruct H. destruct H0.
675 | apply H3 in H1. apply H2 in H1. apply H1.
676 | Qed.
677 |
678 |
679 | Theorem peirce_classic : peirce <-> classic.
680 | Proof.
681 | split.
682 | unfold peirce. unfold classic.
683 | intros. unfold not in H0.
684 | apply H with (Q:=False).
685 | intros. apply H0 in H1. inversion H1.
686 | unfold classic. unfold peirce.
687 | intros. apply H. unfold not. intros.
688 | apply H1. apply H0.
689 | intros. apply H1 in H2. inversion H2.
690 | Qed.
691 |
692 | Theorem classic_excluded_middle : classic <-> excluded_middle.
693 | Proof.
694 | split.
695 | unfold classic. unfold excluded_middle.
696 | intros. apply H. unfold not. intros.
697 | apply H0. right.
698 | intros. destruct H0. left. apply H1.
699 | unfold classic. unfold excluded_middle.
700 | intros. unfold not in H0.
701 | destruct (H P). apply H1.
702 | apply H0 in H1. inversion H1.
703 | Qed.
704 |
705 | Theorem excluded_middle_de_morgan : excluded_middle <-> de_morgan_not_and_not.
706 | Proof.
707 | split.
708 | unfold excluded_middle. unfold de_morgan_not_and_not.
709 | intros.
710 | unfold not in H0.
711 | destruct (H P). left. apply H1.
712 | destruct (H Q). right. apply H2.
713 | destruct H0. split. apply H1. apply H2.
714 | unfold excluded_middle. unfold de_morgan_not_and_not.
715 | intros. apply H.
716 | unfold not.
717 | intros. destruct H0.
718 | apply H1 in H0. apply H0.
719 | Qed.
720 |
721 | Theorem excluded_middle_implies_to_or: excluded_middle <-> implies_to_or.
722 | Proof.
723 | split.
724 | unfold excluded_middle. unfold implies_to_or.
725 | intros.
726 | destruct (H P).
727 | right. apply H0. apply H1.
728 | left. apply H1.
729 | unfold excluded_middle. unfold implies_to_or.
730 | intros.
731 | apply or_commut. apply H.
732 | intros. apply H0.
733 | Qed.
734 |
735 | Theorem de_morgan_implies_to_or : de_morgan_not_and_not <-> implies_to_or.
736 | Proof.
737 | apply equivalent_comm with (Q:=excluded_middle).
738 | apply iff_sym. apply excluded_middle_de_morgan.
739 | apply excluded_middle_implies_to_or.
740 | Qed.
741 |
742 | (* So on and so forth. *)
743 |
744 | (** [] *)
745 |
746 | (** **** Exercise: 3 stars (excluded_middle_irrefutable) *)
747 | (** This theorem implies that it is always safe to add a decidability
748 | axiom (i.e. an instance of excluded middle) for any _particular_ Prop [P].
749 | Why? Because we cannot prove the negation of such an axiom; if we could,
750 | we would have both [~ (P \/ ~P)] and [~ ~ (P \/ ~P)], a contradiction. *)
751 |
752 | Theorem excluded_middle_irrefutable: forall (P:Prop), ~ ~ (P \/ ~ P).
753 | Proof.
754 | intros P.
755 | unfold not. intros. apply H.
756 | right. intros. apply H. left. assumption.
757 | Qed.
758 |
759 | (* ########################################################## *)
760 | (** ** Inequality *)
761 |
762 | (** Saying [x <> y] is just the same as saying [~(x = y)]. *)
763 |
764 | Notation "x <> y" := (~ (x = y)) : type_scope.
765 |
766 | (** Since inequality involves a negation, it again requires
767 | a little practice to be able to work with it fluently. Here
768 | is one very useful trick. If you are trying to prove a goal
769 | that is nonsensical (e.g., the goal state is [false = true]),
770 | apply the lemma [ex_falso_quodlibet] to change the goal to
771 | [False]. This makes it easier to use assumptions of the form
772 | [~P] that are available in the context -- in particular,
773 | assumptions of the form [x<>y]. *)
774 |
775 | Theorem not_false_then_true : forall b : bool,
776 | b <> false -> b = true.
777 | Proof.
778 | intros b H. destruct b.
779 | Case "b = true". reflexivity.
780 | Case "b = false".
781 | unfold not in H.
782 | apply ex_falso_quodlibet.
783 | apply H. reflexivity. Qed.
784 |
785 |
786 | (** *** *)
787 |
788 | (** *** *)
789 |
790 | (** *** *)
791 |
792 | (** *** *)
793 |
794 | (** *** *)
795 |
796 | (** **** Exercise: 2 stars (false_beq_nat) *)
797 | Theorem false_beq_nat : forall n m : nat,
798 | n <> m ->
799 | beq_nat n m = false.
800 | Proof.
801 | intros.
802 | destruct (beq_nat n m) eqn:eq.
803 | unfold not in H. apply beq_nat_true in eq.
804 | apply H in eq. inversion eq.
805 | reflexivity.
806 | Qed.
807 | (** [] *)
808 |
809 | (** **** Exercise: 2 stars, optional (beq_nat_false) *)
810 | Theorem beq_nat_false : forall n m,
811 | beq_nat n m = false -> n <> m.
812 | Proof.
813 | intros.
814 | unfold not.
815 | intros.
816 | rewrite H0 in H. rewrite <- beq_nat_refl in H.
817 | inversion H.
818 | Qed.
819 | (** [] *)
820 |
821 |
822 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
--------------------------------------------------------------------------------
/MoreLogic.v:
--------------------------------------------------------------------------------
1 | (** * MoreLogic: More on Logic in Coq *)
2 |
3 | Require Export "Prop".
4 |
5 | (* ############################################################ *)
6 | (** * Existential Quantification *)
7 |
8 | (** Another critical logical connective is _existential
9 | quantification_. We can express it with the following
10 | definition: *)
11 |
12 | Inductive ex (X:Type) (P : X->Prop) : Prop :=
13 | ex_intro : forall (witness:X), P witness -> ex X P.
14 |
15 | (** That is, [ex] is a family of propositions indexed by a type [X]
16 | and a property [P] over [X]. In order to give evidence for the
17 | assertion "there exists an [x] for which the property [P] holds"
18 | we must actually name a _witness_ -- a specific value [x] -- and
19 | then give evidence for [P x], i.e., evidence that [x] has the
20 | property [P].
21 |
22 | *)
23 |
24 |
25 | (** *** *)
26 | (** Coq's [Notation] facility can be used to introduce more
27 | familiar notation for writing existentially quantified
28 | propositions, exactly parallel to the built-in syntax for
29 | universally quantified propositions. Instead of writing [ex nat
30 | ev] to express the proposition that there exists some number that
31 | is even, for example, we can write [exists x:nat, ev x]. (It is
32 | not necessary to understand exactly how the [Notation] definition
33 | works.) *)
34 |
35 | Notation "'exists' x , p" := (ex _ (fun x => p))
36 | (at level 200, x ident, right associativity) : type_scope.
37 | Notation "'exists' x : X , p" := (ex _ (fun x:X => p))
38 | (at level 200, x ident, right associativity) : type_scope.
39 |
40 | (** *** *)
41 | (** We can use the usual set of tactics for
42 | manipulating existentials. For example, to prove an
43 | existential, we can [apply] the constructor [ex_intro]. Since the
44 | premise of [ex_intro] involves a variable ([witness]) that does
45 | not appear in its conclusion, we need to explicitly give its value
46 | when we use [apply]. *)
47 |
48 | Example exists_example_1 : exists n, n + (n * n) = 6.
49 | Proof.
50 | apply ex_intro with (witness:=2).
51 | reflexivity. Qed.
52 |
53 | (** Note that we have to explicitly give the witness. *)
54 |
55 | (** *** *)
56 | (** Or, instead of writing [apply ex_intro with (witness:=e)] all the
57 | time, we can use the convenient shorthand [exists e], which means
58 | the same thing. *)
59 |
60 | Example exists_example_1' : exists n, n + (n * n) = 6.
61 | Proof.
62 | exists 2.
63 | reflexivity. Qed.
64 |
65 | (** *** *)
66 | (** Conversely, if we have an existential hypothesis in the
67 | context, we can eliminate it with [inversion]. Note the use
68 | of the [as...] pattern to name the variable that Coq
69 | introduces to name the witness value and get evidence that
70 | the hypothesis holds for the witness. (If we don't
71 | explicitly choose one, Coq will just call it [witness], which
72 | makes proofs confusing.) *)
73 |
74 | Theorem exists_example_2 : forall n,
75 | (exists m, n = 4 + m) ->
76 | (exists o, n = 2 + o).
77 | Proof.
78 | intros n H.
79 | inversion H as [m Hm].
80 | exists (2 + m).
81 | apply Hm. Qed.
82 |
83 |
84 | (** Here is another example of how to work with existentials. *)
85 | Lemma exists_example_3 :
86 | exists (n:nat), even n /\ beautiful n.
87 | Proof.
88 | (* WORKED IN CLASS *)
89 | exists 8.
90 | split.
91 | unfold even. simpl. reflexivity.
92 | apply b_sum with (n:=3) (m:=5).
93 | apply b_3. apply b_5.
94 | Qed.
95 |
96 | (** **** Exercise: 1 star, optional (english_exists) *)
97 | (** In English, what does the proposition
98 | ex nat (fun n => beautiful (S n))
99 | ]]
100 | mean? *)
101 |
102 | (*
103 | there is a number n so that [n+1] is beautiful.
104 | *)
105 | (** **** Exercise: 1 star (dist_not_exists) *)
106 | (** Prove that "[P] holds for all [x]" implies "there is no [x] for
107 | which [P] does not hold." *)
108 |
109 | Theorem dist_not_exists : forall (X:Type) (P : X -> Prop),
110 | (forall x, P x) -> ~ (exists x, ~ P x).
111 | Proof.
112 | intros.
113 | unfold not.
114 | intros.
115 | inversion H0. apply H1. apply H.
116 | Qed.
117 | (** [] *)
118 |
119 | (** **** Exercise: 3 stars, optional (not_exists_dist) *)
120 | (** (The other direction of this theorem requires the classical "law
121 | of the excluded middle".) *)
122 |
123 | Theorem not_exists_dist :
124 | excluded_middle ->
125 | forall (X:Type) (P : X -> Prop),
126 | ~ (exists x, ~ P x) -> (forall x, P x).
127 | Proof.
128 | unfold excluded_middle.
129 | unfold not.
130 | intros.
131 | destruct (H (P x)). apply H1.
132 | apply ex_falso_quodlibet.
133 | apply H0. exists x. apply H1.
134 | Qed.
135 | (** [] *)
136 |
137 | (** **** Exercise: 2 stars (dist_exists_or) *)
138 | (** Prove that existential quantification distributes over
139 | disjunction. *)
140 |
141 | Theorem dist_exists_or : forall (X:Type) (P Q : X -> Prop),
142 | (exists x, P x \/ Q x) <-> (exists x, P x) \/ (exists x, Q x).
143 | Proof.
144 | split.
145 | intros.
146 | destruct H. destruct H.
147 | left. exists witness. apply H. right. exists witness. apply H.
148 | intros.
149 | destruct H. destruct H. exists witness. left. apply H.
150 | destruct H. exists witness. right. apply H.
151 | Qed.
152 | (** [] *)
153 |
154 | (* ###################################################### *)
155 | (** * Evidence-Carrying Booleans *)
156 |
157 | (** So far we've seen two different forms of equality predicates:
158 | [eq], which produces a [Prop], and the type-specific forms, like
159 | [beq_nat], that produce [boolean] values. The former are more
160 | convenient to reason about, but we've relied on the latter to let
161 | us use equality tests in _computations_. While it is
162 | straightforward to write lemmas (e.g. [beq_nat_true] and
163 | [beq_nat_false]) that connect the two forms, using these lemmas
164 | quickly gets tedious. *)
165 |
166 | (** *** *)
167 | (** It turns out that we can get the benefits of both forms at once by
168 | using a construct called [sumbool]. *)
169 |
170 | Inductive sumbool (A B : Prop) : Set :=
171 | | left : A -> sumbool A B
172 | | right : B -> sumbool A B.
173 |
174 | Notation "{ A } + { B }" := (sumbool A B) : type_scope.
175 |
176 | (** Think of [sumbool] as being like the [boolean] type, but instead
177 | of its values being just [true] and [false], they carry _evidence_
178 | of truth or falsity. This means that when we [destruct] them, we
179 | are left with the relevant evidence as a hypothesis -- just as
180 | with [or]. (In fact, the definition of [sumbool] is almost the
181 | same as for [or]. The only difference is that values of [sumbool]
182 | are declared to be in [Set] rather than in [Prop]; this is a
183 | technical distinction that allows us to compute with them.) *)
184 |
185 | (** *** *)
186 |
187 | (** Here's how we can define a [sumbool] for equality on [nat]s *)
188 |
189 | Theorem eq_nat_dec : forall n m : nat, {n = m} + {n <> m}.
190 | Proof.
191 | (* WORKED IN CLASS *)
192 | intros n.
193 | induction n as [|n'].
194 | Case "n = 0".
195 | intros m.
196 | destruct m as [|m'].
197 | SCase "m = 0".
198 | left. reflexivity.
199 | SCase "m = S m'".
200 | right. intros contra. inversion contra.
201 | Case "n = S n'".
202 | intros m.
203 | destruct m as [|m'].
204 | SCase "m = 0".
205 | right. intros contra. inversion contra.
206 | SCase "m = S m'".
207 | destruct IHn' with (m := m') as [eq | neq].
208 | left. apply f_equal. apply eq.
209 | right. intros Heq. inversion Heq as [Heq']. apply neq. apply Heq'.
210 | Defined.
211 |
212 | (** Read as a theorem, this says that equality on [nat]s is decidable:
213 | that is, given two [nat] values, we can always produce either
214 | evidence that they are equal or evidence that they are not. Read
215 | computationally, [eq_nat_dec] takes two [nat] values and returns a
216 | [sumbool] constructed with [left] if they are equal and [right] if
217 | they are not; this result can be tested with a [match] or, better,
218 | with an [if-then-else], just like a regular [boolean]. (Notice
219 | that we ended this proof with [Defined] rather than [Qed]. The
220 | only difference this makes is that the proof becomes
221 | _transparent_, meaning that its definition is available when Coq
222 | tries to do reductions, which is important for the computational
223 | interpretation.) *)
224 |
225 | (** *** *)
226 | (** Here's a simple example illustrating the advantages of the
227 | [sumbool] form. *)
228 |
229 | Definition override' {X: Type} (f: nat->X) (k:nat) (x:X) : nat->X:=
230 | fun (k':nat) => if eq_nat_dec k k' then x else f k'.
231 |
232 | Theorem override_same' : forall (X:Type) x1 k1 k2 (f : nat->X),
233 | f k1 = x1 ->
234 | (override' f k1 x1) k2 = f k2.
235 | Proof.
236 | intros X x1 k1 k2 f. intros Hx1.
237 | unfold override'.
238 | destruct (eq_nat_dec k1 k2). (* observe what appears as a hypothesis *)
239 | Case "k1 = k2".
240 | rewrite <- e.
241 | symmetry. apply Hx1.
242 | Case "k1 <> k2".
243 | reflexivity. Qed.
244 |
245 | (** Compare this to the more laborious proof (in MoreCoq.v) for the
246 | version of [override] defined using [beq_nat], where we had to use
247 | the auxiliary lemma [beq_nat_true] to convert a fact about
248 | booleans to a Prop. *)
249 |
250 | (** **** Exercise: 1 star (override_shadow') *)
251 | Theorem override_shadow' : forall (X:Type) x1 x2 k1 k2 (f : nat->X),
252 | (override' (override' f k1 x2) k1 x1) k2 = (override' f k1 x1) k2.
253 | Proof.
254 | intros.
255 | unfold override'.
256 | destruct (eq_nat_dec k1 k2). reflexivity. reflexivity.
257 | Qed.
258 | (** [] *)
259 |
260 |
261 |
262 |
263 |
264 | (* ####################################################### *)
265 | (** * Additional Exercises *)
266 |
267 | (** **** Exercise: 3 stars (all_forallb) *)
268 | (** Inductively define a property [all] of lists, parameterized by a
269 | type [X] and a property [P : X -> Prop], such that [all X P l]
270 | asserts that [P] is true for every element of the list [l]. *)
271 |
272 | Inductive all (X : Type) (P : X -> Prop) : list X -> Prop :=
273 | | all_nil : all X P []
274 | | all_cons : forall (l:list X) (x:X), P x -> all X P l -> all X P (x :: l).
275 |
276 | (** Recall the function [forallb], from the exercise
277 | [forall_exists_challenge] in chapter [MoreCoq]: *)
278 |
279 | Fixpoint forallb {X : Type} (test : X -> bool) (l : list X) : bool :=
280 | match l with
281 | | [] => true
282 | | x :: l' => andb (test x) (forallb test l')
283 | end.
284 |
285 | (** Using the property [all], write down a specification for [forallb],
286 | and prove that it satisfies the specification. Try to make your
287 | specification as precise as possible.
288 |
289 | Are there any important properties of the function [forallb] which
290 | are not captured by your specification? *)
291 |
292 | Theorem all_forallb : forall X (l:list X) (P:X->bool),
293 | forallb P l = true <-> all X (fun x => P x = true) l.
294 | Proof.
295 | intros. split. induction l.
296 | intros. apply all_nil.
297 | simpl. intros. apply all_cons. apply andb_true_elim1 in H. apply H.
298 | apply IHl. apply andb_true_elim2 in H. apply H.
299 | intros. induction l. reflexivity.
300 | simpl. inversion H. rewrite H2. simpl. apply IHl. apply H3.
301 | Qed.
302 | (** [] *)
303 |
304 | (** **** Exercise: 4 stars, advanced (filter_challenge) *)
305 | (** One of the main purposes of Coq is to prove that programs match
306 | their specifications. To this end, let's prove that our
307 | definition of [filter] matches a specification. Here is the
308 | specification, written out informally in English.
309 |
310 | Suppose we have a set [X], a function [test: X->bool], and a list
311 | [l] of type [list X]. Suppose further that [l] is an "in-order
312 | merge" of two lists, [l1] and [l2], such that every item in [l1]
313 | satisfies [test] and no item in [l2] satisfies test. Then [filter
314 | test l = l1].
315 |
316 | A list [l] is an "in-order merge" of [l1] and [l2] if it contains
317 | all the same elements as [l1] and [l2], in the same order as [l1]
318 | and [l2], but possibly interleaved. For example,
319 | [1,4,6,2,3]
320 | is an in-order merge of
321 | [1,6,2]
322 | and
323 | [4,3].
324 | Your job is to translate this specification into a Coq theorem and
325 | prove it. (Hint: You'll need to begin by defining what it means
326 | for one list to be a merge of two others. Do this with an
327 | inductive relation, not a [Fixpoint].) *)
328 |
329 | Inductive in_order_merge {X:Type} : list X -> list X -> list X -> Prop :=
330 | | merge_nil : in_order_merge [] [] []
331 | | merge1 : forall x l1 l2 l3, in_order_merge l1 l2 l3 -> in_order_merge (x :: l1) l2 (x :: l3)
332 | | merge2 : forall x l1 l2 l3, in_order_merge l1 l2 l3 -> in_order_merge l1 (x :: l2) (x :: l3).
333 |
334 | Theorem filter_merge : forall (X:Type) (test:X->bool) (l1 l2 l3:list X),
335 | in_order_merge l1 l2 l3 -> forallb test l1 = true ->
336 | forallb (fun x => negb (test x)) l2 = true ->
337 | filter test l3 = l1.
338 | Proof.
339 | intros X test l1 l2 l3. generalize dependent l1. generalize dependent l2.
340 | induction l3.
341 | intros. inversion H. reflexivity. intros. inversion H.
342 | simpl. destruct (test x) eqn:testeq. apply f_equal. apply IHl3 with (l2:=l2).
343 | apply H5. rewrite <- H3 in H0. simpl in H0. apply andb_true_elim2 in H0.
344 | apply H0. apply H1. rewrite <- H3 in H0. simpl in H0. rewrite <- H2 in testeq.
345 | rewrite testeq in H0. inversion H0.
346 | simpl. rewrite <- H4 in H1. simpl in H1. destruct (test x) eqn:testeq.
347 | rewrite <- H2 in testeq. rewrite testeq in H1. inversion H1.
348 | apply IHl3 with (l2:=l4). apply H5. apply H0. apply andb_true_elim2 in H1.
349 | apply H1.
350 | Qed.
351 | (** [] *)
352 |
353 | (** **** Exercise: 5 stars, advanced, optional (filter_challenge_2) *)
354 | (** A different way to formally characterize the behavior of [filter]
355 | goes like this: Among all subsequences of [l] with the property
356 | that [test] evaluates to [true] on all their members, [filter test
357 | l] is the longest. Express this claim formally and prove it. *)
358 |
359 | Theorem ble_nat_S : forall a b:nat, ble_nat a b = true -> ble_nat a (S b) = true.
360 | Proof.
361 | intros. apply ble_nat_true_trans with (m:=b).
362 | apply H. apply NatList.ble_n_Sn.
363 | Qed.
364 |
365 | Theorem longest : forall (X:Type) (l1 l2:list X) (test:X->bool),
366 | subseq l1 l2 -> forallb test l1 = true ->
367 | ble_nat (length l1) (length (filter test l2)) = true.
368 | Proof.
369 | intros X l1 l2. generalize dependent l1. induction l2.
370 | intros. inversion H. simpl. reflexivity.
371 | intros. inversion H. reflexivity.
372 | simpl. destruct (test x) eqn:testeq. simpl. apply ble_nat_S.
373 | apply IHl2. apply H3. apply H0.
374 | apply IHl2. apply H3. apply H0.
375 | simpl. destruct (test x) eqn:testeq.
376 | destruct (length (x :: filter test l2)) eqn:leneq.
377 | simpl in leneq. inversion leneq. simpl in leneq. inversion leneq.
378 | apply IHl2. apply H3. rewrite <- H2 in H0. simpl in H0.
379 | apply andb_true_elim2 in H0. apply H0.
380 | rewrite <- H2 in H0. simpl in H0. rewrite H1 in H0.
381 | rewrite testeq in H0. inversion H0.
382 | Qed.
383 | (** [] *)
384 |
385 | (** **** Exercise: 4 stars, advanced (no_repeats) *)
386 | (** The following inductively defined proposition... *)
387 |
388 | Inductive appears_in {X:Type} (a:X) : list X -> Prop :=
389 | | ai_here : forall l, appears_in a (a::l)
390 | | ai_later : forall b l, appears_in a l -> appears_in a (b::l).
391 |
392 | (** ...gives us a precise way of saying that a value [a] appears at
393 | least once as a member of a list [l].
394 |
395 | Here's a pair of warm-ups about [appears_in].
396 | *)
397 |
398 | Lemma appears_in_app : forall (X:Type) (xs ys : list X) (x:X),
399 | appears_in x (xs ++ ys) -> appears_in x xs \/ appears_in x ys.
400 | Proof.
401 | intros X xs. induction xs.
402 | intros. right. apply H.
403 | intros. inversion H. left. apply ai_here.
404 | apply IHxs in H1. inversion H1. left. apply ai_later. apply H3.
405 | right. apply H3.
406 | Qed.
407 |
408 | Lemma app_appears_in : forall (X:Type) (xs ys : list X) (x:X),
409 | appears_in x xs \/ appears_in x ys -> appears_in x (xs ++ ys).
410 | Proof.
411 | intros X xs. induction xs. intros. inversion H.
412 | inversion H0. apply H0. intros.
413 | inversion H. inversion H0. rewrite cons_app. apply ai_here.
414 | rewrite cons_app. apply ai_later. apply IHxs. left. apply H2.
415 | rewrite cons_app. apply ai_later. apply IHxs. right. apply H0.
416 | Qed.
417 |
418 |
419 | (** Now use [appears_in] to define a proposition [disjoint X l1 l2],
420 | which should be provable exactly when [l1] and [l2] are
421 | lists (with elements of type X) that have no elements in common. *)
422 |
423 | Definition disjoint {X:Type} (l1 l2:list X) : Prop :=
424 | forall x, ~ ((appears_in x l1) /\ (appears_in x l2)).
425 |
426 | (** Next, use [appears_in] to define an inductive proposition
427 | [no_repeats X l], which should be provable exactly when [l] is a
428 | list (with elements of type [X]) where every member is different
429 | from every other. For example, [no_repeats nat [1,2,3,4]] and
430 | [no_repeats bool []] should be provable, while [no_repeats nat
431 | [1,2,1]] and [no_repeats bool [true,true]] should not be. *)
432 |
433 | Inductive no_repeats {X:Type} : list X -> Prop :=
434 | | nore1 : forall x, no_repeats [x]
435 | | nore_cons : forall x l, ~ (appears_in x l) -> no_repeats l -> no_repeats (x :: l).
436 |
437 | (** Finally, state and prove one or more interesting theorems relating
438 | [disjoint], [no_repeats] and [++] (list append). *)
439 |
440 | Theorem disjoin_nore_append : forall (X:Type) (l1 l2:list X),
441 | no_repeats l1 -> no_repeats l2 -> disjoint l1 l2 -> no_repeats (l1 ++ l2).
442 | Proof.
443 | intros X l1. induction l1.
444 | intros. apply H0.
445 | intros. inversion H. apply nore_cons.
446 | unfold disjoint in H1.
447 | unfold not. intros. destruct (H1 x).
448 | split. apply ai_here. apply H2. apply H0.
449 | rewrite cons_app. apply nore_cons.
450 | unfold not. intros.
451 | unfold disjoint in H1. apply appears_in_app in H6.
452 | destruct H6. apply contradiction_implies_anything with (P:=appears_in x l1).
453 | split. apply H6. apply H4. destruct (H1 x).
454 | split. apply ai_here. apply H6. apply IHl1.
455 | apply H5. apply H0.
456 | unfold disjoint in H1. unfold disjoint.
457 | intros. unfold not. intros.
458 | destruct H6. destruct (H1 x1). split.
459 | apply ai_later. apply H6. apply H7.
460 | Qed.
461 |
462 | (** **** Exercise: 3 stars (nostutter) *)
463 | (** Formulating inductive definitions of predicates is an important
464 | skill you'll need in this course. Try to solve this exercise
465 | without any help at all.
466 |
467 | We say that a list of numbers "stutters" if it repeats the same
468 | number consecutively. The predicate "[nostutter mylist]" means
469 | that [mylist] does not stutter. Formulate an inductive definition
470 | for [nostutter]. (This is different from the [no_repeats]
471 | predicate in the exercise above; the sequence [1;4;1] repeats but
472 | does not stutter.) *)
473 |
474 | Inductive nostutter: list nat -> Prop :=
475 | | nostu_nil : nostutter nil
476 | | nostu1 : forall x, nostutter [x]
477 | | nostu_cons : forall x y l, x <> y -> nostutter (y :: l) -> nostutter (x :: y :: l).
478 |
479 | (** Make sure each of these tests succeeds, but you are free
480 | to change the proof if the given one doesn't work for you.
481 | Your definition might be different from mine and still correct,
482 | in which case the examples might need a different proof.
483 |
484 | The suggested proofs for the examples (in comments) use a number
485 | of tactics we haven't talked about, to try to make them robust
486 | with respect to different possible ways of defining [nostutter].
487 | You should be able to just uncomment and use them as-is, but if
488 | you prefer you can also prove each example with more basic
489 | tactics. *)
490 |
491 | Example test_nostutter_1: nostutter [3;1;4;1;5;6].
492 |
493 | Proof. repeat constructor; apply beq_nat_false; auto. Qed.
494 |
495 | Example test_nostutter_2: nostutter [].
496 | Proof. apply nostu_nil. Qed.
497 | (*
498 | Proof. repeat constructor; apply beq_nat_false; auto. Qed.
499 | *)
500 |
501 | Example test_nostutter_3: nostutter [5].
502 | Proof. apply nostu1. Qed.
503 | (*
504 | Proof. repeat constructor; apply beq_nat_false; auto. Qed.
505 | *)
506 |
507 | Example test_nostutter_4: not (nostutter [3;1;1;4]).
508 | Proof.
509 | unfold not. intros. inversion H.
510 | inversion H4. unfold not in H7.
511 | apply H7. reflexivity.
512 | Qed.
513 | (* Proof. intro. *)
514 | (* repeat match goal with *)
515 | (* h: nostutter _ |- _ => inversion h; clear h; subst *)
516 | (* end. *)
517 | (* contradiction H1; auto. Qed. *)
518 | (** [] *)
519 |
520 | (** **** Exercise: 4 stars, advanced (pigeonhole principle) *)
521 | (** The "pigeonhole principle" states a basic fact about counting:
522 | if you distribute more than [n] items into [n] pigeonholes, some
523 | pigeonhole must contain at least two items. As is often the case,
524 | this apparently trivial fact about numbers requires non-trivial
525 | machinery to prove, but we now have enough... *)
526 |
527 | (** First a pair of useful lemmas (we already proved these for lists
528 | of naturals, but not for arbitrary lists). *)
529 |
530 | Lemma app_length : forall (X:Type) (l1 l2 : list X),
531 | length (l1 ++ l2) = length l1 + length l2.
532 | Proof.
533 | intros X l1. induction l1.
534 | simpl. intros. reflexivity.
535 | simpl. intros. apply f_equal. apply IHl1.
536 | Qed.
537 |
538 | Lemma appears_in_app_split : forall (X:Type) (x:X) (l:list X),
539 | appears_in x l ->
540 | exists l1, exists l2, l = l1 ++ (x::l2).
541 | Proof.
542 | intros. induction l.
543 | inversion H. inversion H.
544 | exists nil. exists l. reflexivity.
545 | apply IHl in H1. destruct H1. destruct H1.
546 | exists (x0 :: witness). exists witness0. simpl. rewrite <- H1.
547 | reflexivity.
548 | Qed.
549 |
550 | (** Now define a predicate [repeats] (analogous to [no_repeats] in the
551 | exercise above), such that [repeats X l] asserts that [l] contains
552 | at least one repeated element (of type [X]). *)
553 |
554 | Inductive repeats {X:Type} : list X -> Prop :=
555 | | rep_here : forall x l, appears_in x l -> repeats (x :: l)
556 | | rep_later : forall x l, repeats l -> repeats (x :: l).
557 |
558 | (** Now here's a way to formalize the pigeonhole principle. List [l2]
559 | represents a list of pigeonhole labels, and list [l1] represents
560 | the labels assigned to a list of items: if there are more items
561 | than labels, at least two items must have the same label. This
562 | proof is much easier if you use the [excluded_middle] hypothesis
563 | to show that [appears_in] is decidable, i.e. [forall x
564 | l, (appears_in x l) \/ ~ (appears_in x l)]. However, it is also
565 | possible to make the proof go through _without_ assuming that
566 | [appears_in] is decidable; if you can manage to do this, you will
567 | not need the [excluded_middle] hypothesis. *)
568 | Theorem pigeonhole_principle: forall (X:Type) (l1 l2:list X),
569 | excluded_middle ->
570 | (forall x, appears_in x l1 -> appears_in x l2) ->
571 | length l2 < length l1 ->
572 | repeats l1.
573 | Proof.
574 | intros X l1. induction l1 as [|x l1']; intros.
575 | inversion H1.
576 | destruct (H (appears_in x l1')).
577 | apply rep_here. apply H2. apply rep_later.
578 | destruct (H (appears_in x l2)). apply appears_in_app_split in H3.
579 | inversion H3. inversion H4.
580 | apply IHl1' with (l2:=(witness ++ witness0)).
581 | apply H. intros. destruct (H (x0 = x)). subst. contradiction.
582 | apply ai_later with (b:=x) in H6. apply H0 in H6.
583 | rewrite H5 in H6. apply appears_in_app in H6. apply app_appears_in.
584 | destruct H6. left. apply H6. right.
585 | inversion H6. contradiction. assumption.
586 | rewrite H5 in H1. rewrite app_length in H1.
587 | simpl in H1. rewrite <- plus_n_Sm in H1.
588 | apply Sn_le_Sm__n_le_m in H1.
589 | unfold lt. rewrite app_length. apply H1.
590 | apply contradiction_implies_anything with (P:=(appears_in x l2)).
591 | split. apply H0. apply ai_here. apply H3.
592 | Qed.
593 | (** [] *)
594 |
595 | (** $Date: 2014-12-31 16:01:37 -0500 (Wed, 31 Dec 2014) $ *)
596 |
--------------------------------------------------------------------------------
/Postscript.v:
--------------------------------------------------------------------------------
1 | (** * Postscript *)
2 |
3 | (** * Looking back... *)
4 |
5 | (** - _Functional programming_
6 | - "declarative" programming (recursion over persistent data
7 | structures)
8 | - higher-order functions
9 | - polymorphism *)
10 |
11 | (**
12 | - _Logic_, the mathematical basis for software engineering:
13 | <<
14 | logic calculus
15 | -------------------- = ----------------------------
16 | software engineering mechanical/civil engineering
17 | >>
18 |
19 | - inductively defined sets and relations
20 | - inductive proofs
21 | - proof objects *)
22 |
23 | (**
24 | - _Coq_, an industrial-strength proof assistant
25 | - functional core language
26 | - core tactics
27 | - automation
28 | *)
29 |
30 | (**
31 | - _Foundations of programming languages_
32 |
33 | - notations and definitional techniques for precisely specifying
34 | - abstract syntax
35 | - operational semantics
36 | - big-step style
37 | - small-step style
38 | - type systems
39 |
40 | - program equivalence
41 |
42 | - Hoare logic
43 |
44 | - fundamental metatheory of type systems
45 |
46 | - progress and preservation
47 |
48 | - theory of subtyping
49 | *)
50 |
51 | (* ###################################################################### *)
52 | (** * Looking forward... *)
53 |
54 | (** Some good places to go for more...
55 |
56 | - Several optional chapters of _Software Foundations_
57 |
58 | - Cutting-edge conferences on programming languages and formal
59 | verification:
60 | - POPL
61 | - PLDI
62 | - OOPSLA
63 | - ICFP
64 | - CAV
65 | - (and many others)
66 |
67 | - More on functional programming
68 | - Learn You a Haskell for Great Good, by Miran
69 | Lipovaca (ebook)
70 | - and many other texts on Haskell, OCaml, Scheme, Scala, ...
71 |
72 | - More on Hoare logic and program verification
73 | - The Formal Semantics of Programming Languages: An
74 | Introduction, by Glynn Winskel. MIT Press, 1993.
75 | - Many practical verification tools, e.g. Microsoft's
76 | Boogie system, Java Extended Static Checking, etc.
77 |
78 | - More on the foundations of programming languages:
79 | - Types and Programming Languages, by Benjamin C. Pierce. MIT
80 | Press, 2002.
81 | - Practical Foundations for Programming Languages, by Robert
82 | Harper. Forthcoming from MIT Press. Manuscript available
83 | from his web page.
84 | - Foundations for Programming Languages, by John C. Mitchell.
85 | MIT Press, 1996.
86 |
87 | - More on Coq:
88 | - Certified Programming with Dependent Types, by Adam
89 | Chlipala. A draft textbook on practical proof
90 | engineering with Coq, available from his web page.
91 | - Interactive Theorem Proving and Program Development:
92 | Coq'Art: The Calculus of Inductive Constructions, by Yves
93 | Bertot and Pierre Casteran. Springer-Verlag, 2004.
94 | - Iron Lambda (http://iron.ouroborus.net/) is a collection
95 | of Coq formalisations for functional languages of
96 | increasing complexity. It fills part of the gap between
97 | the end of the Software Foundations course and what
98 | appears in current research papers. The collection has
99 | at least Progress and Preservation theorems for a number
100 | of variants of STLC and the polymorphic
101 | lambda-calculus (System F)
102 |
103 | *)
104 |
105 | (* $Date: 2014-08-23 15:24:59 -0400 (Sat, 23 Aug 2014) $ *)
106 |
107 |
--------------------------------------------------------------------------------
/Preface.v:
--------------------------------------------------------------------------------
1 | (** * Preface *)
2 |
3 | (* ###################################################################### *)
4 | (** * Welcome *)
5 |
6 | (** This electronic book is a course on _Software Foundations_, the
7 | mathematical underpinnings of reliable software. Topics include
8 | basic concepts of logic, computer-assisted theorem proving, the
9 | Coq proof assistant, functional programming, operational
10 | semantics, Hoare logic, and static type systems. The exposition
11 | is intended for a broad range of readers, from advanced
12 | undergraduates to PhD students and researchers. No specific
13 | background in logic or programming languages is assumed, though a
14 | degree of mathematical maturity will be helpful.
15 |
16 | The principal novelty of the course is that it is one hundred per
17 | cent formalized and machine-checked: the entire text is literally
18 | a script for Coq. It is intended to be read alongside an
19 | interactive session with Coq. All the details in the text are
20 | fully formalized in Coq, and the exercises are designed to be
21 | worked using Coq.
22 |
23 | The files are organized into a sequence of core chapters, covering
24 | about one semester's worth of material and organized into a
25 | coherent linear narrative, plus a number of "appendices" covering
26 | additional topics. All the core chapters are suitable for both
27 | upper-level undergraduate and graduate students. *)
28 |
29 |
30 | (* ###################################################################### *)
31 | (** * Overview *)
32 |
33 | (** Building reliable software is hard. The scale and complexity of
34 | modern systems, the number of people involved in building them,
35 | and the range of demands placed on them make it extremely
36 | difficult even to build software that is more or less correct,
37 | much less to get it 100%% correct. At the same time, the
38 | increasing degree to which information processing is woven into
39 | every aspect of society continually amplifies the cost of bugs and
40 | insecurities.
41 |
42 | Computer scientists and software engineers have responded to these
43 | challenges by developing a whole host of techniques for improving
44 | software reliability, ranging from recommendations about managing
45 | software projects and organizing programming teams (e.g., extreme
46 | programming) to design philosophies for libraries (e.g.,
47 | model-view-controller, publish-subscribe, etc.) and programming
48 | languages (e.g., object-oriented programming, aspect-oriented
49 | programming, functional programming, ...) and to mathematical
50 | techniques for specifying and reasoning about properties of
51 | software and tools for helping validate these properties.
52 |
53 | The present course is focused on this last set of techniques. The
54 | text weaves together five conceptual threads:
55 |
56 | (1) basic tools from _logic_ for making and justifying precise
57 | claims about programs;
58 |
59 | (2) the use of _proof assistants_ to construct rigorous logical
60 | arguments;
61 |
62 | (3) the idea of _functional programming_, both as a method of
63 | programming and as a bridge between programming and logic;
64 |
65 | (4) formal techniques for _reasoning about the properties of
66 | specific programs_ (e.g., the fact that a loop terminates on
67 | all inputs, or that a sorting function or a compiler obeys a
68 | particular specification); and
69 |
70 | (5) the use of _type systems_ for establishing well-behavedness
71 | guarantees for _all_ programs in a given programming
72 | language (e.g., the fact that well-typed Java programs cannot
73 | be subverted at runtime).
74 |
75 | Each of these topics is easily rich enough to fill a whole course
76 | in its own right; taking all of them together naturally means that
77 | much will be left unsaid. But we hope readers will find that the
78 | themes illuminate and amplify each other in useful ways, and that
79 | bringing them together creates a foundation from which it will be
80 | easy to dig into any of them more deeply. Some suggestions for
81 | further reading can be found in the [Postscript] chapter. *)
82 |
83 | (** ** Logic *)
84 |
85 | (** Logic is the field of study whose subject matter is _proofs_ --
86 | unassailable arguments for the truth of particular propositions.
87 | Volumes have been written about the central role of logic in
88 | computer science. Manna and Waldinger called it "the calculus of
89 | computer science," while Halpern et al.'s paper _On the Unusual
90 | Effectiveness of Logic in Computer Science_ catalogs scores of
91 | ways in which logic offers critical tools and insights. Indeed,
92 | they observe that "As a matter of fact, logic has turned out to be
93 | significiantly more effective in computer science than it has been
94 | in mathematics. This is quite remarkable, especially since much
95 | of the impetus for the development of logic during the past one
96 | hundred years came from mathematics."
97 |
98 | In particular, the fundamental notion of inductive proofs is
99 | ubiquitous in all of computer science. You have surely seen them
100 | before, in contexts from discrete math to analysis of algorithms,
101 | but in this course we will examine them much more deeply than you
102 | have probably done so far. *)
103 |
104 | (** ** Proof Assistants *)
105 |
106 | (** The flow of ideas between logic and computer science has not been
107 | in just one direction: CS has also made important contributions to
108 | logic. One of these has been the development of software tools
109 | for helping construct proofs of logical propositions. These tools
110 | fall into two broad categories:
111 |
112 | - _Automated theorem provers_ provide "push-button" operation:
113 | you give them a proposition and they return either _true_,
114 | _false_, or _ran out of time_. Although their capabilities
115 | are limited to fairly specific sorts of reasoning, they have
116 | matured tremendously in recent years and are used now in a
117 | huge variety of settings. Examples of such tools include SAT
118 | solvers, SMT solvers, and model checkers.
119 |
120 | - _Proof assistants_ are hybrid tools that automate the more
121 | routine aspects of building proofs while depending on human
122 | guidance for more difficult aspects. Widely used proof
123 | assistants include Isabelle, Agda, Twelf, ACL2, PVS, and Coq,
124 | among many others.
125 |
126 | This course is based around Coq, a proof assistant that has been
127 | under development since 1983 at a number of French research labs
128 | and universities. Coq provides a rich environment for interactive
129 | development of machine-checked formal reasoning. The kernel of
130 | the Coq system is a simple proof-checker which guarantees that
131 | only correct deduction steps are performed. On top of this
132 | kernel, the Coq environment provides high-level facilities for
133 | proof development, including powerful tactics for constructing
134 | complex proofs semi-automatically, and a large library of common
135 | definitions and lemmas.
136 |
137 | Coq has been a critical enabler for a huge variety of work across
138 | computer science and mathematics:
139 |
140 | - As a _platform for modeling programming languages_, it has become
141 | a standard tool for researchers who need to describe and reason
142 | about complex language definitions. It has been used, for
143 | example, to check the security of the JavaCard platform,
144 | obtaining the highest level of common criteria certification,
145 | and for formal specifications of the x86 and LLVM instruction
146 | sets.
147 |
148 | - As an _environment for developing formally certified software_,
149 | Coq has been used to build CompCert, a fully-verified optimizing
150 | compiler for C, for proving the correctness of subtle algorithms
151 | involving floating point numbers, and as the basis for
152 | Certicrypt, an environment for reasoning about the security of
153 | cryptographic algorithms.
154 |
155 | - As a _realistic environment for programming with dependent
156 | types_, it has inspired numerous innovations. For example, the
157 | Ynot project at Harvard embeds "relational Hoare reasoning" (an
158 | extension of the _Hoare Logic_ we will see later in this course)
159 | in Coq.
160 |
161 | - As a _proof assistant for higher-order logic_, it has been used
162 | to validate a number of important results in mathematics. For
163 | example, its ability to include complex computations inside
164 | proofs made it possible to develop the first formally verified
165 | proof of the 4-color theorem. This proof had previously been
166 | controversial among mathematicians because part of it included
167 | checking a large number of configurations using a program. In
168 | the Coq formalization, everything is checked, including the
169 | correctness of the computational part. More recently, an even
170 | more massive effort led to a Coq formalization of the
171 | Feit-Thompson Theorem -- the first major step in the
172 | classification of finite simple groups.
173 |
174 | By the way, in case you're wondering about the name, here's what
175 | the official Coq web site says: "Some French computer scientists
176 | have a tradition of naming their software as animal species: Caml,
177 | Elan, Foc or Phox are examples of this tacit convention. In French,
178 | 'coq' means rooster, and it sounds like the initials of the
179 | Calculus of Constructions (CoC) on which it is based." The rooster
180 | is also the national symbol of France, and "Coq" are the first
181 | three letters of the name of Thierry Coquand, one of Coq's early
182 | developers. *)
183 |
184 | (** ** Functional Programming *)
185 |
186 | (** The term _functional programming_ refers both to a collection of
187 | programming idioms that can be used in almost any programming
188 | language and to a family of programming languages designed to
189 | emphasize these idioms, including Haskell, OCaml, Standard ML,
190 | F##, Scala, Scheme, Racket, Common Lisp, Clojure, Erlang, and Coq.
191 |
192 | Functional programming has been developed over many decades --
193 | indeed, its roots go back to Church's lambda-calculus, which was
194 | invented in the 1930s before the era of the computer began! But
195 | since the early '90s it has enjoyed a surge of interest among
196 | industrial engineers and language designers, playing a key role in
197 | high-value systems at companies like Jane St. Capital, Microsoft,
198 | Facebook, and Ericsson.
199 |
200 | The most basic tenet of functional programming is that, as much as
201 | possible, computation should be _pure_, in the sense that the only
202 | effect of execution should be to produce a result: the computation
203 | should be free from _side effects_ such as I/O, assignments to
204 | mutable variables, redirecting pointers, etc. For example,
205 | whereas an _imperative_ sorting function might take a list of
206 | numbers and rearrange its pointers to put the list in order, a
207 | pure sorting function would take the original list and return a
208 | _new_ list containing the same numbers in sorted order.
209 |
210 | One significant benefit of this style of programming is that it
211 | makes programs easier to understand and reason about. If every
212 | operation on a data structure yields a new data structure, leaving
213 | the old one intact, then there is no need to worry about how that
214 | structure is being shared and whether a change by one part of the
215 | program might break an invariant that another part of the program
216 | relies on. These considerations are particularly critical in
217 | concurrent programs, where every piece of mutable state that is
218 | shared between threads is a potential source of pernicious bugs.
219 | Indeed, a large part of the recent interest in functional
220 | programming in industry is due to its simple behavior in the
221 | presence of concurrency.
222 |
223 | Another reason for the current excitement about functional
224 | programming is related to the first: functional programs are often
225 | much easier to parallelize than their imperative counterparts. If
226 | running a computation has no effect other than producing a result,
227 | then it does not matter _where_ it is run. Similarly, if a data
228 | structure is never modified destructively, then it can be copied
229 | freely, across cores or across the network. Indeed, the MapReduce
230 | idiom that lies at the heart of massively distributed query
231 | processors like Hadoop and is used by Google to index the entire
232 | web is a classic example of functional programming.
233 |
234 | For purposes of this course, functional programming has yet
235 | another significant attraction: it serves as a bridge between
236 | logic and computer science. Indeed, Coq itself can be viewed as a
237 | combination of a small but extremely expressive functional
238 | programming language plus with a set of tools for stating and
239 | proving logical assertions. Moreover, when we come to look more
240 | closely, we find that these two sides of Coq are actually aspects
241 | of the very same underlying machinery -- i.e., _proofs are
242 | programs_. *)
243 |
244 | (** ** Program Verification *)
245 |
246 | (** The first third of the book is devoted to developing the
247 | conceptual framework of logic and functional programming and
248 | gaining enough fluency with Coq to use it for modeling and
249 | reasoning about nontrivial artifacts. From this point on, we
250 | increasingly turn our attention to two broad topics of critical
251 | importance to the enterprise of building reliable software (and
252 | hardware): techniques for proving specific properties of
253 | particular _programs_ and for proving general properties of whole
254 | programming _languages_.
255 |
256 | For both of these, the first thing we need is a way of
257 | representing programs as mathematical objects, so we can talk
258 | about them precisely, and ways of describing their behavior in
259 | terms of mathematical functions or relations. Our tools for these
260 | tasks are _abstract syntax_ and _operational semantics_, a method
261 | of specifying the behavior of programs by writing abstract
262 | interpreters. At the beginning, we work with operational
263 | semantics in the so-called "big-step" style, which leads to
264 | somewhat simpler and more readable definitions, in those cases
265 | where it is applicable. Later on, we switch to a more detailed
266 | "small-step" style, which helps make some useful distinctions
267 | between different sorts of "nonterminating" program behaviors and
268 | which is applicable to a broader range of language features,
269 | including concurrency.
270 |
271 | The first programming language we consider in detail is _Imp_, a
272 | tiny toy language capturing the core features of conventional
273 | imperative programming: variables, assignment, conditionals, and
274 | loops. We study two different ways of reasoning about the
275 | properties of Imp programs.
276 |
277 | First, we consider what it means to say that two Imp programs are
278 | _equivalent_ in the sense that they give the same behaviors for
279 | all initial memories. This notion of equivalence then becomes a
280 | criterion for judging the correctness of _metaprograms_ --
281 | programs that manipulate other programs, such as compilers and
282 | optimizers. We build a simple optimizer for Imp and prove that it
283 | is correct.
284 |
285 | Second, we develop a methodology for proving that Imp programs
286 | satisfy formal specifications of their behavior. We introduce the
287 | notion of _Hoare triples_ -- Imp programs annotated with pre- and
288 | post-conditions describing what should be true about the memory in
289 | which they are started and what they promise to make true about
290 | the memory in which they terminate -- and the reasoning principles
291 | of _Hoare Logic_, a "domain-specific logic" specialized for
292 | convenient compositional reasoning about imperative programs, with
293 | concepts like "loop invariant" built in.
294 |
295 | This part of the course is intended to give readers a taste of the
296 | key ideas and mathematical tools used for a wide variety of
297 | real-world software and hardware verification tasks.
298 | *)
299 |
300 | (** ** Type Systems *)
301 |
302 | (** Our final major topic, covering the last third of the course, is
303 | _type systems_, a powerful set of tools for establishing
304 | properties of _all_ programs in a given language.
305 |
306 | Type systems are the best established and most popular example of
307 | a highly successful class of formal verification techniques known
308 | as _lightweight formal methods_. These are reasoning techniques
309 | of modest power -- modest enough that automatic checkers can be
310 | built into compilers, linkers, or program analyzers and thus be
311 | applied even by programmers unfamiliar with the underlying
312 | theories. (Other examples of lightweight formal methods include
313 | hardware and software model checkers, contract checkers, and
314 | run-time property monitoring techniques for detecting when some
315 | component of a system is not behaving according to specification).
316 |
317 | This topic brings us full circle: the language whose properties we
318 | study in this part, called the _simply typed lambda-calculus_, is
319 | essentially a simplified model of the core of Coq itself!
320 |
321 | *)
322 |
323 | (* ###################################################################### *)
324 | (** * Practicalities *)
325 |
326 | (* ###################################################################### *)
327 | (** ** Chapter Dependencies *)
328 |
329 | (** A diagram of the dependencies between chapters and some suggested
330 | paths through the material can be found in the file [deps.html]. *)
331 |
332 | (* ###################################################################### *)
333 | (** ** System Requirements *)
334 |
335 | (** Coq runs on Windows, Linux, and OS X. You will need:
336 |
337 | - A current installation of Coq, available from the Coq home
338 | page. Everything should work with version 8.4.
339 |
340 | - An IDE for interacting with Coq. Currently, there are two
341 | choices:
342 |
343 | - Proof General is an Emacs-based IDE. It tends to be
344 | preferred by users who are already comfortable with
345 | Emacs. It requires a separate installation (google
346 | "Proof General").
347 |
348 | - CoqIDE is a simpler stand-alone IDE. It is distributed
349 | with Coq, but on some platforms compiling it involves
350 | installing additional packages for GUI libraries and
351 | such. *)
352 |
353 | (* ###################################################################### *)
354 | (** ** Exercises *)
355 |
356 | (** Each chapter includes numerous exercises. Each is marked with a
357 | "star rating," which can be interpreted as follows:
358 |
359 | - One star: easy exercises that underscore points in the text
360 | and that, for most readers, should take only a minute or two.
361 | Get in the habit of working these as you reach them.
362 |
363 | - Two stars: straightforward exercises (five or ten minutes).
364 |
365 | - Three stars: exercises requiring a bit of thought (ten
366 | minutes to half an hour).
367 |
368 | - Four and five stars: more difficult exercises (half an hour
369 | and up).
370 |
371 | Also, some exercises are marked "advanced", and some are marked
372 | "optional." Doing just the non-optional, non-advanced exercises
373 | should provide good coverage of the core material. Optional
374 | exercises provide a bit of extra practice with key concepts and
375 | introduce secondary themes that may be of interest to some
376 | readers. Advanced exercises are for readers who want an extra
377 | challenge (and, in return, a deeper contact with the material).
378 |
379 | _Please do not post solutions to the exercises in public places_:
380 | Software Foundations is widely used both for self-study and for
381 | university courses. Having solutions easily available makes it
382 | much less useful for courses, which typically have graded homework
383 | assignments. The authors especially request that readers not post
384 | solutions to the exercises anyplace where they can be found by
385 | search engines.
386 | *)
387 |
388 | (* ###################################################################### *)
389 | (** ** Downloading the Coq Files *)
390 |
391 | (** A tar file containing the full sources for the "release version"
392 | of these notes (as a collection of Coq scripts and HTML files) is
393 | available here:
394 | <<
395 | http://www.cis.upenn.edu/~bcpierce/sf
396 | >>
397 | If you are using the notes as part of a class, you may be given
398 | access to a locally extended version of the files, which you
399 | should use instead of the release version.
400 | *)
401 |
402 | (* ###################################################################### *)
403 | (** * Note for Instructors *)
404 |
405 | (** If you intend to use these materials in your own course, you will
406 | undoubtedly find things you'd like to change, improve, or add.
407 | Your contributions are welcome!
408 |
409 | Please send an email to Benjamin Pierce describing yourself and
410 | how you would like to use the materials, and including the result
411 | of doing "htpasswd -s -n NAME", where NAME is your preferred user
412 | name. We'll set you up with read/write access to our subversion
413 | repository and developers' mailing list; in the repository you'll
414 | find a [README] with further instructions. *)
415 |
416 | (* ###################################################################### *)
417 | (** * Translations *)
418 |
419 | (** Thanks to the efforts of a team of volunteer translators, _Software
420 | Foundations_ can now be enjoyed in Japanese at [http://proofcafe.org/sf]
421 | *)
422 |
423 | (** $Date: 2014-12-31 15:31:47 -0500 (Wed, 31 Dec 2014) $ *)
424 |
425 |
--------------------------------------------------------------------------------
/ProofObjects.v:
--------------------------------------------------------------------------------
1 | (** * ProofObjects: Working with Explicit Evidence in Coq *)
2 |
3 | Require Export MoreLogic.
4 |
5 | (* ##################################################### *)
6 |
7 | (** We have seen that Coq has mechanisms both for _programming_,
8 | using inductive data types (like [nat] or [list]) and functions
9 | over these types, and for _proving_ properties of these programs,
10 | using inductive propositions (like [ev] or [eq]), implication, and
11 | universal quantification. So far, we have treated these mechanisms
12 | as if they were quite separate, and for many purposes this is
13 | a good way to think. But we have also seen hints that Coq's programming and
14 | proving facilities are closely related. For example, the
15 | keyword [Inductive] is used to declare both data types and
16 | propositions, and [->] is used both to describe the type of
17 | functions on data and logical implication. This is not just a
18 | syntactic accident! In fact, programs and proofs in Coq are almost
19 | the same thing. In this chapter we will study how this works.
20 |
21 | We have already seen the fundamental idea: provability in Coq is
22 | represented by concrete _evidence_. When we construct the proof
23 | of a basic proposition, we are actually building a tree of evidence,
24 | which can be thought of as a data structure. If the proposition
25 | is an implication like [A -> B], then its proof will be an
26 | evidence _transformer_: a recipe for converting evidence for
27 | A into evidence for B. So at a fundamental level, proofs are simply
28 | programs that manipulate evidence.
29 | *)
30 | (**
31 | Q. If evidence is data, what are propositions themselves?
32 |
33 | A. They are types!
34 |
35 | Look again at the formal definition of the [beautiful] property. *)
36 |
37 | Print beautiful.
38 | (* ==>
39 | Inductive beautiful : nat -> Prop :=
40 | b_0 : beautiful 0
41 | | b_3 : beautiful 3
42 | | b_5 : beautiful 5
43 | | b_sum : forall n m : nat, beautiful n -> beautiful m -> beautiful (n + m)
44 | *)
45 |
46 | (** *** *)
47 |
48 | (** The trick is to introduce an alternative pronunciation of "[:]".
49 | Instead of "has type," we can also say "is a proof of." For
50 | example, the second line in the definition of [beautiful] declares
51 | that [b_0 : beautiful 0]. Instead of "[b_0] has type
52 | [beautiful 0]," we can say that "[b_0] is a proof of [beautiful 0]."
53 | Similarly for [b_3] and [b_5]. *)
54 |
55 | (** *** *)
56 |
57 | (** This pun between types and propositions (between [:] as "has type"
58 | and [:] as "is a proof of" or "is evidence for") is called the
59 | _Curry-Howard correspondence_. It proposes a deep connection
60 | between the world of logic and the world of computation.
61 | <<
62 | propositions ~ types
63 | proofs ~ data values
64 | >>
65 | Many useful insights follow from this connection. To begin with, it
66 | gives us a natural interpretation of the type of [b_sum] constructor: *)
67 |
68 | Check b_sum.
69 | (* ===> b_sum : forall n m,
70 | beautiful n ->
71 | beautiful m ->
72 | beautiful (n+m) *)
73 | (** This can be read "[b_sum] is a constructor that takes four
74 | arguments -- two numbers, [n] and [m], and two pieces of evidence,
75 | for the propositions [beautiful n] and [beautiful m], respectively --
76 | and yields evidence for the proposition [beautiful (n+m)]." *)
77 |
78 | (** Now let's look again at a previous proof involving [beautiful]. *)
79 |
80 | Theorem eight_is_beautiful: beautiful 8.
81 | Proof.
82 | apply b_sum with (n := 3) (m := 5).
83 | apply b_3.
84 | apply b_5. Qed.
85 |
86 | (** Just as with ordinary data values and functions, we can use the [Print]
87 | command to see the _proof object_ that results from this proof script. *)
88 |
89 | Print eight_is_beautiful.
90 | (* ===> eight_is_beautiful = b_sum 3 5 b_3 b_5
91 | : beautiful 8 *)
92 |
93 | (** In view of this, we might wonder whether we can write such
94 | an expression ourselves. Indeed, we can: *)
95 |
96 | Check (b_sum 3 5 b_3 b_5).
97 | (* ===> beautiful (3 + 5) *)
98 |
99 | (** The expression [b_sum 3 5 b_3 b_5] can be thought of as
100 | instantiating the parameterized constructor [b_sum] with the
101 | specific arguments [3] [5] and the corresponding proof objects for
102 | its premises [beautiful 3] and [beautiful 5] (Coq is smart enough
103 | to figure out that 3+5=8). Alternatively, we can think of [b_sum]
104 | as a primitive "evidence constructor" that, when applied to two
105 | particular numbers, wants to be further applied to evidence that
106 | those two numbers are beautiful; its type,
107 | forall n m, beautiful n -> beautiful m -> beautiful (n+m),
108 | expresses this functionality, in the same way that the polymorphic
109 | type [forall X, list X] in the previous chapter expressed the fact
110 | that the constructor [nil] can be thought of as a function from
111 | types to empty lists with elements of that type. *)
112 |
113 | (** This gives us an alternative way to write the proof that [8] is
114 | beautiful: *)
115 |
116 | Theorem eight_is_beautiful': beautiful 8.
117 | Proof.
118 | apply (b_sum 3 5 b_3 b_5).
119 | Qed.
120 |
121 | (** Notice that we're using [apply] here in a new way: instead of just
122 | supplying the _name_ of a hypothesis or previously proved theorem
123 | whose type matches the current goal, we are supplying an
124 | _expression_ that directly builds evidence with the required
125 | type. *)
126 |
127 |
128 | (* ##################################################### *)
129 | (** * Proof Scripts and Proof Objects *)
130 |
131 | (** These proof objects lie at the core of how Coq operates.
132 |
133 | When Coq is following a proof script, what is happening internally
134 | is that it is gradually constructing a proof object -- a term
135 | whose type is the proposition being proved. The tactics between
136 | the [Proof] command and the [Qed] instruct Coq how to build up a
137 | term of the required type. To see this process in action, let's
138 | use the [Show Proof] command to display the current state of the
139 | proof tree at various points in the following tactic proof. *)
140 |
141 | Theorem eight_is_beautiful'': beautiful 8.
142 | Proof.
143 | Show Proof.
144 | apply b_sum with (n:=3) (m:=5).
145 | Show Proof.
146 | apply b_3.
147 | Show Proof.
148 | apply b_5.
149 | Show Proof.
150 | Qed.
151 |
152 | (** At any given moment, Coq has constructed a term with some
153 | "holes" (indicated by [?1], [?2], and so on), and it knows what
154 | type of evidence is needed at each hole. *)
155 |
156 | (**
157 | Each of the holes corresponds to a subgoal, and the proof is
158 | finished when there are no more subgoals. At this point, the
159 | [Theorem] command gives a name to the evidence we've built and
160 | stores it in the global context. *)
161 |
162 | (** Tactic proofs are useful and convenient, but they are not
163 | essential: in principle, we can always construct the required
164 | evidence by hand, as shown above. Then we can use [Definition]
165 | (rather than [Theorem]) to give a global name directly to a
166 | piece of evidence. *)
167 |
168 | Definition eight_is_beautiful''' : beautiful 8 :=
169 | b_sum 3 5 b_3 b_5.
170 |
171 | (** All these different ways of building the proof lead to exactly the
172 | same evidence being saved in the global environment. *)
173 |
174 | Print eight_is_beautiful.
175 | (* ===> eight_is_beautiful = b_sum 3 5 b_3 b_5 : beautiful 8 *)
176 | Print eight_is_beautiful'.
177 | (* ===> eight_is_beautiful' = b_sum 3 5 b_3 b_5 : beautiful 8 *)
178 | Print eight_is_beautiful''.
179 | (* ===> eight_is_beautiful'' = b_sum 3 5 b_3 b_5 : beautiful 8 *)
180 | Print eight_is_beautiful'''.
181 | (* ===> eight_is_beautiful''' = b_sum 3 5 b_3 b_5 : beautiful 8 *)
182 |
183 | (** **** Exercise: 1 star (six_is_beautiful) *)
184 | (** Give a tactic proof and a proof object showing that [6] is [beautiful]. *)
185 |
186 | Theorem six_is_beautiful :
187 | beautiful 6.
188 | Proof.
189 | apply (b_sum 3 3 b_3 b_3).
190 | Qed.
191 |
192 | Definition six_is_beautiful' : beautiful 6 :=
193 | b_sum 3 3 b_3 b_3.
194 | (** [] *)
195 |
196 | (** **** Exercise: 1 star (nine_is_beautiful) *)
197 | (** Give a tactic proof and a proof object showing that [9] is [beautiful]. *)
198 |
199 | Theorem nine_is_beautiful :
200 | beautiful 9.
201 | Proof.
202 | apply (b_sum 3 6 b_3 six_is_beautiful).
203 | Qed.
204 |
205 | Definition nine_is_beautiful' : beautiful 9 :=
206 | b_sum 3 6 b_3 six_is_beautiful.
207 | (** [] *)
208 |
209 | (* ##################################################### *)
210 | (** * Quantification, Implications and Functions *)
211 |
212 | (** In Coq's computational universe (where we've mostly been living
213 | until this chapter), there are two sorts of values with arrows in
214 | their types: _constructors_ introduced by [Inductive]-ly defined
215 | data types, and _functions_.
216 |
217 | Similarly, in Coq's logical universe, there are two ways of giving
218 | evidence for an implication: constructors introduced by
219 | [Inductive]-ly defined propositions, and... functions!
220 |
221 | For example, consider this statement: *)
222 |
223 | Theorem b_plus3: forall n, beautiful n -> beautiful (3+n).
224 | Proof.
225 | intros n H.
226 | apply b_sum.
227 | apply b_3.
228 | apply H.
229 | Qed.
230 |
231 | (** What is the proof object corresponding to [b_plus3]?
232 |
233 | We're looking for an expression whose _type_ is [forall n,
234 | beautiful n -> beautiful (3+n)] -- that is, a _function_ that
235 | takes two arguments (one number and a piece of evidence) and
236 | returns a piece of evidence! Here it is: *)
237 |
238 | Definition b_plus3' : forall n, beautiful n -> beautiful (3+n) :=
239 | fun (n : nat) => fun (H : beautiful n) =>
240 | b_sum 3 n b_3 H.
241 |
242 | Check b_plus3'.
243 | (* ===> b_plus3' : forall n : nat, beautiful n -> beautiful (3+n) *)
244 |
245 | (** Recall that [fun n => blah] means "the function that, given [n],
246 | yields [blah]." Another equivalent way to write this definition is: *)
247 |
248 | Definition b_plus3'' (n : nat) (H : beautiful n) : beautiful (3+n) :=
249 | b_sum 3 n b_3 H.
250 |
251 | Check b_plus3''.
252 | (* ===> b_plus3'' : forall n, beautiful n -> beautiful (3+n) *)
253 |
254 | (** When we view the proposition being proved by [b_plus3] as a function type,
255 | one aspect of it may seem a little unusual. The second argument's
256 | type, [beautiful n], mentions the _value_ of the first argument, [n].
257 | While such _dependent types_ are not commonly found in programming
258 | languages, even functional ones like ML or Haskell, they can
259 | be useful there too.
260 |
261 | Notice that both implication ([->]) and quantification ([forall])
262 | correspond to functions on evidence. In fact, they are really the
263 | same thing: [->] is just a shorthand for a degenerate use of
264 | [forall] where there is no dependency, i.e., no need to give a name
265 | to the type on the LHS of the arrow. *)
266 |
267 | (** For example, consider this proposition: *)
268 |
269 | Definition beautiful_plus3 : Prop :=
270 | forall n, forall (E : beautiful n), beautiful (n+3).
271 |
272 | (** A proof term inhabiting this proposition would be a function
273 | with two arguments: a number [n] and some evidence [E] that [n] is
274 | beautiful. But the name [E] for this evidence is not used in the
275 | rest of the statement of [funny_prop1], so it's a bit silly to
276 | bother making up a name for it. We could write it like this
277 | instead, using the dummy identifier [_] in place of a real
278 | name: *)
279 |
280 | Definition beautiful_plus3' : Prop :=
281 | forall n, forall (_ : beautiful n), beautiful (n+3).
282 |
283 | (** Or, equivalently, we can write it in more familiar notation: *)
284 |
285 | Definition beatiful_plus3'' : Prop :=
286 | forall n, beautiful n -> beautiful (n+3).
287 |
288 | (** In general, "[P -> Q]" is just syntactic sugar for
289 | "[forall (_:P), Q]". *)
290 |
291 |
292 | (** **** Exercise: 2 stars b_times2 *)
293 |
294 | (** Give a proof object corresponding to the theorem [b_times2] from Prop.v *)
295 | Definition b_times2': forall n, beautiful n -> beautiful (2*n) :=
296 | fun n => fun h => b_times2 n h.
297 | (** [] *)
298 |
299 |
300 |
301 | (** **** Exercise: 2 stars, optional (gorgeous_plus13_po) *)
302 | (** Give a proof object corresponding to the theorem [gorgeous_plus13] from Prop.v *)
303 |
304 | Definition gorgeous_plus13_po: forall n, gorgeous n -> gorgeous (13+n):=
305 | fun n => fun h => gorgeous_plus13 n h.
306 | (** [] *)
307 |
308 |
309 |
310 |
311 | (** It is particularly revealing to look at proof objects involving the
312 | logical connectives that we defined with inductive propositions in Logic.v. *)
313 |
314 | Theorem and_example :
315 | (beautiful 0) /\ (beautiful 3).
316 | Proof.
317 | apply conj.
318 | (* Case "left". *) apply b_0.
319 | (* Case "right". *) apply b_3. Qed.
320 |
321 | (** Let's take a look at the proof object for the above theorem. *)
322 |
323 | Print and_example.
324 | (* ===> conj (beautiful 0) (beautiful 3) b_0 b_3
325 | : beautiful 0 /\ beautiful 3 *)
326 |
327 | (** Note that the proof is of the form
328 | conj (beautiful 0) (beautiful 3)
329 | (...pf of beautiful 3...) (...pf of beautiful 3...)
330 | as you'd expect, given the type of [conj]. *)
331 |
332 | (** **** Exercise: 1 star, optional (case_proof_objects) *)
333 | (** The [Case] tactics were commented out in the proof of
334 | [and_example] to avoid cluttering the proof object. What would
335 | you guess the proof object will look like if we uncomment them?
336 | Try it and see. *)
337 | (** [] *)
338 |
339 | Theorem and_commut : forall P Q : Prop,
340 | P /\ Q -> Q /\ P.
341 | Proof.
342 | intros P Q H.
343 | inversion H as [HP HQ].
344 | split.
345 | Case "left". apply HQ.
346 | Case "right". apply HP. Qed.
347 |
348 | (** Once again, we have commented out the [Case] tactics to make the
349 | proof object for this theorem easier to understand. It is still
350 | a little complicated, but after performing some simple reduction
351 | steps, we can see that all that is really happening is taking apart
352 | a record containing evidence for [P] and [Q] and rebuilding it in the
353 | opposite order: *)
354 |
355 | Print and_commut.
356 | (* ===>
357 | and_commut =
358 | fun (P Q : Prop) (H : P /\ Q) =>
359 | (fun H0 : Q /\ P => H0)
360 | match H with
361 | | conj HP HQ => (fun (HP0 : P) (HQ0 : Q) => conj Q P HQ0 HP0) HP HQ
362 | end
363 | : forall P Q : Prop, P /\ Q -> Q /\ P *)
364 |
365 | (** After simplifying some direct application of [fun] expressions to arguments,
366 | we get: *)
367 |
368 | (* ===>
369 | and_commut =
370 | fun (P Q : Prop) (H : P /\ Q) =>
371 | match H with
372 | | conj HP HQ => conj Q P HQ HP
373 | end
374 | : forall P Q : Prop, P /\ Q -> Q /\ P *)
375 |
376 |
377 |
378 | (** **** Exercise: 2 stars, optional (conj_fact) *)
379 | (** Construct a proof object demonstrating the following proposition. *)
380 |
381 | Definition conj_fact : forall P Q R, P /\ Q -> Q /\ R -> P /\ R :=
382 | fun P Q R H1 H2 =>
383 | match H1 with
384 | | conj HP HQ => match H2 with
385 | | conj HQ HR =>
386 | conj P R HP HR
387 | end
388 | end.
389 | (** [] *)
390 |
391 |
392 |
393 | (** **** Exercise: 2 stars, advanced, optional (beautiful_iff_gorgeous) *)
394 |
395 | (** We have seen that the families of propositions [beautiful] and
396 | [gorgeous] actually characterize the same set of numbers.
397 | Prove that [beautiful n <-> gorgeous n] for all [n]. Just for
398 | fun, write your proof as an explicit proof object, rather than
399 | using tactics. (_Hint_: if you make use of previously defined
400 | theorems, you should only need a single line!) *)
401 |
402 | Definition beautiful_iff_gorgeous :
403 | forall n, beautiful n <-> gorgeous n :=
404 | fun n => conj (beautiful n -> gorgeous n) (gorgeous n -> beautiful n) (beautiful__gorgeous n) (gorgeous__beautiful n).
405 | (** [] *)
406 |
407 |
408 | (** **** Exercise: 2 stars, optional (or_commut'') *)
409 | (** Try to write down an explicit proof object for [or_commut] (without
410 | using [Print] to peek at the ones we already defined!). *)
411 |
412 | Definition or_commut : forall (P Q:Prop), P \/ Q -> Q \/ P :=
413 | fun P Q H => match H with
414 | | or_introl P0 => or_intror Q P P0
415 | | or_intror Q0 => or_introl Q P Q0
416 | end.
417 | (** [] *)
418 |
419 | (** Recall that we model an existential for a property as a pair consisting of
420 | a witness value and a proof that the witness obeys that property.
421 | We can choose to construct the proof explicitly.
422 |
423 | For example, consider this existentially quantified proposition: *)
424 | Check ex.
425 |
426 | Definition some_nat_is_even : Prop :=
427 | ex _ ev.
428 |
429 | (** To prove this proposition, we need to choose a particular number
430 | as witness -- say, 4 -- and give some evidence that that number is
431 | even. *)
432 |
433 | Definition snie : some_nat_is_even :=
434 | ex_intro _ ev 4 (ev_SS 2 (ev_SS 0 ev_0)).
435 |
436 |
437 | (** **** Exercise: 2 stars, optional (ex_beautiful_Sn) *)
438 | (** Complete the definition of the following proof object: *)
439 |
440 | Definition p : ex _ (fun n => beautiful (S n)) :=
441 | ex_intro _ (fun n => beautiful (S n)) 2 b_3.
442 | (** [] *)
443 |
444 |
445 |
446 | (* ##################################################### *)
447 | (** * Giving Explicit Arguments to Lemmas and Hypotheses *)
448 |
449 | (** Even when we are using tactic-based proof, it can be very useful to
450 | understand the underlying functional nature of implications and quantification.
451 |
452 | For example, it is often convenient to [apply] or [rewrite]
453 | using a lemma or hypothesis with one or more quantifiers or
454 | assumptions already instantiated in order to direct what
455 | happens. For example: *)
456 |
457 | Check plus_comm.
458 | (* ==>
459 | plus_comm
460 | : forall n m : nat, n + m = m + n *)
461 |
462 | Lemma plus_comm_r : forall a b c, c + (b + a) = c + (a + b).
463 | Proof.
464 | intros a b c.
465 | (* rewrite plus_comm. *)
466 | (* rewrites in the first possible spot; not what we want *)
467 | rewrite (plus_comm b a). (* directs rewriting to the right spot *)
468 | reflexivity. Qed.
469 |
470 |
471 | (** In this case, giving just one argument would be sufficient. *)
472 |
473 | Lemma plus_comm_r' : forall a b c, c + (b + a) = c + (a + b).
474 | Proof.
475 | intros a b c.
476 | rewrite (plus_comm b).
477 | reflexivity. Qed.
478 |
479 | (** Arguments must be given in order, but wildcards (_)
480 | may be used to skip arguments that Coq can infer. *)
481 |
482 | Lemma plus_comm_r'' : forall a b c, c + (b + a) = c + (a + b).
483 | Proof.
484 | intros a b c.
485 | rewrite (plus_comm _ a).
486 | reflexivity. Qed.
487 |
488 | (** The author of a lemma can choose to declare easily inferable arguments
489 | to be implicit, just as with functions and constructors.
490 |
491 | The [with] clauses we've already seen is really just a way of
492 | specifying selected arguments by name rather than position: *)
493 |
494 | Lemma plus_comm_r''' : forall a b c, c + (b + a) = c + (a + b).
495 | Proof.
496 | intros a b c.
497 | rewrite plus_comm with (n := b).
498 | reflexivity. Qed.
499 |
500 |
501 | (** **** Exercise: 2 stars (trans_eq_example_redux) *)
502 | (** Redo the proof of the following theorem (from MoreCoq.v) using
503 | an [apply] of [trans_eq] but _not_ using a [with] clause. *)
504 |
505 | Example trans_eq_example' : forall (a b c d e f : nat),
506 | [a;b] = [c;d] ->
507 | [c;d] = [e;f] ->
508 | [a;b] = [e;f].
509 | Proof.
510 | intros.
511 | apply (trans_eq (list nat) [a; b] [c; d] [e; f]).
512 | apply H. apply H0.
513 | Qed.
514 | (** [] *)
515 |
516 |
517 |
518 | (* ##################################################### *)
519 | (** * Programming with Tactics (Advanced) *)
520 |
521 | (** If we can build proofs with explicit terms rather than tactics,
522 | you may be wondering if we can build programs using tactics rather
523 | than explicit terms. Sure! *)
524 |
525 | Definition add1 : nat -> nat.
526 | intro n.
527 | Show Proof.
528 | apply S.
529 | Show Proof.
530 | apply n. Defined.
531 |
532 | Print add1.
533 | (* ==>
534 | add1 = fun n : nat => S n
535 | : nat -> nat
536 | *)
537 |
538 | Eval compute in add1 2.
539 |
540 | Definition add1' (n:nat) :nat.
541 | Show Proof.
542 | apply S.
543 | Show Proof.
544 | apply n. Defined.
545 |
546 | (* ==> 3 : nat *)
547 |
548 | (** Notice that we terminate the [Definition] with a [.] rather than with
549 | [:=] followed by a term. This tells Coq to enter proof scripting mode
550 | to build an object of type [nat -> nat]. Also, we terminate the proof
551 | with [Defined] rather than [Qed]; this makes the definition _transparent_
552 | so that it can be used in computation like a normally-defined function.
553 |
554 | This feature is mainly useful for writing functions with dependent types,
555 | which we won't explore much further in this book.
556 | But it does illustrate the uniformity and orthogonality of the basic ideas in Coq. *)
557 |
558 | (** $Date: 2014-12-31 15:31:47 -0500 (Wed, 31 Dec 2014) $ *)
559 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Software-Foundations-Solutions
2 |
--------------------------------------------------------------------------------
/Rel.v:
--------------------------------------------------------------------------------
1 | (** * Rel: Properties of Relations *)
2 |
3 | Require Export SfLib.
4 |
5 | (** This short, optional chapter develops some basic definitions and a
6 | few theorems about binary relations in Coq. The key definitions
7 | are repeated where they are actually used (in the [Smallstep]
8 | chapter), so readers who are already comfortable with these ideas
9 | can safely skim or skip this chapter. However, relations are also
10 | a good source of exercises for developing facility with Coq's
11 | basic reasoning facilities, so it may be useful to look at it just
12 | after the [Logic] chapter. *)
13 |
14 | (** A (binary) _relation_ on a set [X] is a family of propositions
15 | parameterized by two elements of [X] -- i.e., a proposition about
16 | pairs of elements of [X]. *)
17 |
18 | Definition relation (X: Type) := X -> X -> Prop.
19 |
20 | (** Somewhat confusingly, the Coq standard library hijacks the generic
21 | term "relation" for this specific instance. To maintain
22 | consistency with the library, we will do the same. So, henceforth
23 | the Coq identifier [relation] will always refer to a binary
24 | relation between some set and itself, while the English word
25 | "relation" can refer either to the specific Coq concept or the
26 | more general concept of a relation between any number of possibly
27 | different sets. The context of the discussion should always make
28 | clear which is meant. *)
29 |
30 | (** An example relation on [nat] is [le], the less-that-or-equal-to
31 | relation which we usually write like this [n1 <= n2]. *)
32 |
33 | Print le.
34 | (* ====> Inductive le (n : nat) : nat -> Prop :=
35 | le_n : n <= n
36 | | le_S : forall m : nat, n <= m -> n <= S m *)
37 | Check le : nat -> nat -> Prop.
38 | Check le : relation nat.
39 |
40 | (* ######################################################### *)
41 | (** * Basic Properties of Relations *)
42 |
43 | (** As anyone knows who has taken an undergraduate discrete math
44 | course, there is a lot to be said about relations in general --
45 | ways of classifying relations (are they reflexive, transitive,
46 | etc.), theorems that can be proved generically about classes of
47 | relations, constructions that build one relation from another,
48 | etc. For example... *)
49 |
50 | (** A relation [R] on a set [X] is a _partial function_ if, for every
51 | [x], there is at most one [y] such that [R x y] -- i.e., if [R x
52 | y1] and [R x y2] together imply [y1 = y2]. *)
53 |
54 | Definition partial_function {X: Type} (R: relation X) :=
55 | forall x y1 y2 : X, R x y1 -> R x y2 -> y1 = y2.
56 |
57 | (** For example, the [next_nat] relation defined earlier is a partial
58 | function. *)
59 |
60 | Print next_nat.
61 | (* ====> Inductive next_nat (n : nat) : nat -> Prop :=
62 | nn : next_nat n (S n) *)
63 | Check next_nat : relation nat.
64 |
65 | Theorem next_nat_partial_function :
66 | partial_function next_nat.
67 | Proof.
68 | unfold partial_function.
69 | intros x y1 y2 H1 H2.
70 | inversion H1. inversion H2.
71 | reflexivity. Qed.
72 |
73 | (** However, the [<=] relation on numbers is not a partial function.
74 | In short: Assume, for a contradiction, that [<=] is a partial
75 | function. But then, since [0 <= 0] and [0 <= 1], it follows that
76 | [0 = 1]. This is nonsense, so our assumption was
77 | contradictory. *)
78 |
79 | Theorem le_not_a_partial_function :
80 | ~ (partial_function le).
81 | Proof.
82 | unfold not. unfold partial_function. intros Hc.
83 | assert (0 = 1) as Nonsense.
84 | Case "Proof of assertion".
85 | apply Hc with (x := 0).
86 | apply le_n.
87 | apply le_S. apply le_n.
88 | inversion Nonsense. Qed.
89 |
90 | (** **** Exercise: 2 stars, optional *)
91 | (** Show that the [total_relation] defined in earlier is not a partial
92 | function. *)
93 |
94 | Print total_relation.
95 | Theorem total_relation_not_a_partial_function :
96 | ~ (partial_function total_relation).
97 | Proof.
98 | unfold not. unfold partial_function. intros.
99 | assert (0 = 1) as Nonsense.
100 | apply H with 0. apply tot. apply tot.
101 | inversion Nonsense.
102 | Qed.
103 | (** [] *)
104 |
105 | (** **** Exercise: 2 stars, optional *)
106 | (** Show that the [empty_relation] defined earlier is a partial
107 | function. *)
108 |
109 | Print empty_relation.
110 | Theorem empty_relation_is_a_partial_function :
111 | partial_function empty_relation.
112 | Proof.
113 | unfold partial_function. intros.
114 | inversion H.
115 | Qed.
116 | (** [] *)
117 |
118 | (** A _reflexive_ relation on a set [X] is one for which every element
119 | of [X] is related to itself. *)
120 |
121 | Definition reflexive {X: Type} (R: relation X) :=
122 | forall a : X, R a a.
123 |
124 | Theorem le_reflexive :
125 | reflexive le.
126 | Proof.
127 | unfold reflexive. intros n. apply le_n. Qed.
128 |
129 | (** A relation [R] is _transitive_ if [R a c] holds whenever [R a b]
130 | and [R b c] do. *)
131 |
132 | Definition transitive {X: Type} (R: relation X) :=
133 | forall a b c : X, (R a b) -> (R b c) -> (R a c).
134 |
135 | Theorem le_trans :
136 | transitive le.
137 | Proof.
138 | intros n m o Hnm Hmo.
139 | induction Hmo.
140 | Case "le_n". apply Hnm.
141 | Case "le_S". apply le_S. apply IHHmo. Qed.
142 |
143 | Theorem lt_trans:
144 | transitive lt.
145 | Proof.
146 | unfold lt. unfold transitive.
147 | intros n m o Hnm Hmo.
148 | apply le_S in Hnm.
149 | apply le_trans with (a := (S n)) (b := (S m)) (c := o).
150 | apply Hnm.
151 | apply Hmo. Qed.
152 |
153 | (** **** Exercise: 2 stars, optional *)
154 | (** We can also prove [lt_trans] more laboriously by induction,
155 | without using le_trans. Do this.*)
156 |
157 | Theorem lt_trans' :
158 | transitive lt.
159 | Proof.
160 | (* Prove this by induction on evidence that [m] is less than [o]. *)
161 | unfold lt. unfold transitive.
162 | intros n m o Hnm Hmo.
163 | induction Hmo as [| m' Hm'o].
164 | apply le_S. apply Hnm. apply le_S. apply IHHm'o.
165 | Qed.
166 | (** [] *)
167 |
168 | (** **** Exercise: 2 stars, optional *)
169 | (** Prove the same thing again by induction on [o]. *)
170 |
171 | Theorem lt_trans'' :
172 | transitive lt.
173 | Proof.
174 | unfold lt. unfold transitive.
175 | intros n m o Hnm Hmo.
176 | induction o as [| o'].
177 | inversion Hmo. apply le_S. inversion Hmo. rewrite <- H0.
178 | apply Hnm. apply IHo'. apply H0.
179 | Qed.
180 | (** [] *)
181 |
182 | (** The transitivity of [le], in turn, can be used to prove some facts
183 | that will be useful later (e.g., for the proof of antisymmetry
184 | below)... *)
185 |
186 | Theorem le_Sn_le : forall n m, S n <= m -> n <= m.
187 | Proof.
188 | intros n m H. apply le_trans with (S n).
189 | apply le_S. apply le_n.
190 | apply H. Qed.
191 |
192 | (** **** Exercise: 1 star, optional *)
193 | Theorem le_S_n : forall n m,
194 | (S n <= S m) -> (n <= m).
195 | Proof.
196 | intros. inversion H. reflexivity.
197 | apply le_trans with (S n). apply le_S. apply le_n.
198 | apply H1.
199 | Qed.
200 | (** [] *)
201 |
202 | (** **** Exercise: 2 stars, optional (le_Sn_n_inf) *)
203 | (** Provide an informal proof of the following theorem:
204 |
205 | Theorem: For every [n], [~(S n <= n)]
206 |
207 | A formal proof of this is an optional exercise below, but try
208 | the informal proof without doing the formal proof first.
209 |
210 | Proof:
211 | ...
212 | []
213 | *)
214 |
215 | (** **** Exercise: 1 star, optional *)
216 | Theorem le_Sn_n : forall n,
217 | ~ (S n <= n).
218 | Proof.
219 | unfold not. intros.
220 | induction n. inversion H. apply IHn.
221 | inversion H. apply H. apply le_trans with (S (S n)).
222 | apply le_S. apply le_n. apply H1.
223 | Qed.
224 | (** [] *)
225 |
226 | (** Reflexivity and transitivity are the main concepts we'll need for
227 | later chapters, but, for a bit of additional practice working with
228 | relations in Coq, here are a few more common ones.
229 |
230 | A relation [R] is _symmetric_ if [R a b] implies [R b a]. *)
231 |
232 | Definition symmetric {X: Type} (R: relation X) :=
233 | forall a b : X, (R a b) -> (R b a).
234 |
235 | (** **** Exercise: 2 stars, optional *)
236 | Theorem le_not_symmetric :
237 | ~ (symmetric le).
238 | Proof.
239 | unfold not. unfold symmetric.
240 | intros.
241 | assert (1 <= 0).
242 | apply H. apply le_S. apply le_n.
243 | inversion H0.
244 | Qed.
245 | (** [] *)
246 |
247 | (** A relation [R] is _antisymmetric_ if [R a b] and [R b a] together
248 | imply [a = b] -- that is, if the only "cycles" in [R] are trivial
249 | ones. *)
250 |
251 | Definition antisymmetric {X: Type} (R: relation X) :=
252 | forall a b : X, (R a b) -> (R b a) -> a = b.
253 |
254 | (** **** Exercise: 2 stars, optional *)
255 | Theorem le_antisymmetric :
256 | antisymmetric le.
257 | Proof.
258 | unfold antisymmetric.
259 | intros a. induction a.
260 | intros. inversion H. reflexivity. rewrite <- H2 in H0. inversion H0.
261 | intros. destruct b. inversion H. apply f_equal.
262 | apply IHa. apply le_S_n. apply H. apply le_S_n. apply H0.
263 | Qed.
264 | (** [] *)
265 |
266 | (** **** Exercise: 2 stars, optional *)
267 | Theorem le_step : forall n m p,
268 | n < m ->
269 | m <= S p ->
270 | n <= p.
271 | Proof.
272 | unfold lt.
273 | intros.
274 | apply le_S_n. apply le_trans with m.
275 | apply H. apply H0.
276 | Qed.
277 | (** [] *)
278 |
279 | (** A relation is an _equivalence_ if it's reflexive, symmetric, and
280 | transitive. *)
281 |
282 | Definition equivalence {X:Type} (R: relation X) :=
283 | (reflexive R) /\ (symmetric R) /\ (transitive R).
284 |
285 | (** A relation is a _partial order_ when it's reflexive,
286 | _anti_-symmetric, and transitive. In the Coq standard library
287 | it's called just "order" for short. *)
288 |
289 | Definition order {X:Type} (R: relation X) :=
290 | (reflexive R) /\ (antisymmetric R) /\ (transitive R).
291 |
292 | (** A preorder is almost like a partial order, but doesn't have to be
293 | antisymmetric. *)
294 |
295 | Definition preorder {X:Type} (R: relation X) :=
296 | (reflexive R) /\ (transitive R).
297 |
298 | Theorem le_order :
299 | order le.
300 | Proof.
301 | unfold order. split.
302 | Case "refl". apply le_reflexive.
303 | split.
304 | Case "antisym". apply le_antisymmetric.
305 | Case "transitive.". apply le_trans. Qed.
306 |
307 | (* ########################################################### *)
308 | (** * Reflexive, Transitive Closure *)
309 |
310 | (** The _reflexive, transitive closure_ of a relation [R] is the
311 | smallest relation that contains [R] and that is both reflexive and
312 | transitive. Formally, it is defined like this in the Relations
313 | module of the Coq standard library: *)
314 |
315 | Inductive clos_refl_trans {A: Type} (R: relation A) : relation A :=
316 | | rt_step : forall x y, R x y -> clos_refl_trans R x y
317 | | rt_refl : forall x, clos_refl_trans R x x
318 | | rt_trans : forall x y z,
319 | clos_refl_trans R x y ->
320 | clos_refl_trans R y z ->
321 | clos_refl_trans R x z.
322 |
323 | (** For example, the reflexive and transitive closure of the
324 | [next_nat] relation coincides with the [le] relation. *)
325 |
326 | Theorem next_nat_closure_is_le : forall n m,
327 | (n <= m) <-> ((clos_refl_trans next_nat) n m).
328 | Proof.
329 | intros n m. split.
330 | Case "->".
331 | intro H. induction H.
332 | SCase "le_n". apply rt_refl.
333 | SCase "le_S".
334 | apply rt_trans with m. apply IHle. apply rt_step. apply nn.
335 | Case "<-".
336 | intro H. induction H.
337 | SCase "rt_step". inversion H. apply le_S. apply le_n.
338 | SCase "rt_refl". apply le_n.
339 | SCase "rt_trans".
340 | apply le_trans with y.
341 | apply IHclos_refl_trans1.
342 | apply IHclos_refl_trans2. Qed.
343 |
344 | (** The above definition of reflexive, transitive closure is
345 | natural -- it says, explicitly, that the reflexive and transitive
346 | closure of [R] is the least relation that includes [R] and that is
347 | closed under rules of reflexivity and transitivity. But it turns
348 | out that this definition is not very convenient for doing
349 | proofs -- the "nondeterminism" of the [rt_trans] rule can sometimes
350 | lead to tricky inductions.
351 |
352 | Here is a more useful definition... *)
353 |
354 | Inductive refl_step_closure {X:Type} (R: relation X) : relation X :=
355 | | rsc_refl : forall (x : X), refl_step_closure R x x
356 | | rsc_step : forall (x y z : X),
357 | R x y ->
358 | refl_step_closure R y z ->
359 | refl_step_closure R x z.
360 |
361 | (** (Note that, aside from the naming of the constructors, this
362 | definition is the same as the [multi] step relation used in many
363 | other chapters.) *)
364 |
365 | (** (The following [Tactic Notation] definitions are explained in
366 | another chapter. You can ignore them if you haven't read the
367 | explanation yet.) *)
368 |
369 | Tactic Notation "rt_cases" tactic(first) ident(c) :=
370 | first;
371 | [ Case_aux c "rt_step" | Case_aux c "rt_refl"
372 | | Case_aux c "rt_trans" ].
373 |
374 | Tactic Notation "rsc_cases" tactic(first) ident(c) :=
375 | first;
376 | [ Case_aux c "rsc_refl" | Case_aux c "rsc_step" ].
377 |
378 | (** Our new definition of reflexive, transitive closure "bundles"
379 | the [rt_step] and [rt_trans] rules into the single rule step.
380 | The left-hand premise of this step is a single use of [R],
381 | leading to a much simpler induction principle.
382 |
383 | Before we go on, we should check that the two definitions do
384 | indeed define the same relation...
385 |
386 | First, we prove two lemmas showing that [refl_step_closure] mimics
387 | the behavior of the two "missing" [clos_refl_trans]
388 | constructors. *)
389 |
390 | Theorem rsc_R : forall (X:Type) (R:relation X) (x y : X),
391 | R x y -> refl_step_closure R x y.
392 | Proof.
393 | intros X R x y H.
394 | apply rsc_step with y. apply H. apply rsc_refl. Qed.
395 |
396 | (** **** Exercise: 2 stars, optional (rsc_trans) *)
397 | Theorem rsc_trans :
398 | forall (X:Type) (R: relation X) (x y z : X),
399 | refl_step_closure R x y ->
400 | refl_step_closure R y z ->
401 | refl_step_closure R x z.
402 | Proof.
403 | intros. induction H. apply H0.
404 | apply rsc_step with y. apply H. apply IHrefl_step_closure.
405 | apply H0.
406 | Qed.
407 | (** [] *)
408 |
409 | (** Then we use these facts to prove that the two definitions of
410 | reflexive, transitive closure do indeed define the same
411 | relation. *)
412 |
413 | (** **** Exercise: 3 stars, optional (rtc_rsc_coincide) *)
414 | Theorem rtc_rsc_coincide :
415 | forall (X:Type) (R: relation X) (x y : X),
416 | clos_refl_trans R x y <-> refl_step_closure R x y.
417 | Proof.
418 | split.
419 | Case "clos_refl -> refl_step".
420 | intros. induction H. apply rsc_R. apply H.
421 | apply rsc_refl. apply rsc_trans with y. apply IHclos_refl_trans1.
422 | apply IHclos_refl_trans2.
423 | Case "refl_step -> clos_refl".
424 | intros. induction H. apply rt_refl.
425 | apply rt_trans with y. apply rt_step. apply H. apply IHrefl_step_closure.
426 | Qed.
427 | (** [] *)
428 |
429 | (** $Date: 2014-12-31 15:31:47 -0500 (Wed, 31 Dec 2014) $ *)
430 |
--------------------------------------------------------------------------------
/SepLogic.v:
--------------------------------------------------------------------------------
1 | Require Export Imp.
2 |
3 | (* First we define syntax of the language *)
4 |
5 | (* We could reuse aexp and bexp defined for Imp. *)
6 |
7 | (* Redefine commands here. To distinguish them
8 | from Imp commands, we call them scom *)
9 | (* You need to change it into an inductive definition *)
10 | Inductive scom : Type :=
11 | | SCSkip : scom
12 | | SCAss : id -> aexp -> scom
13 | | SCSeq : scom -> scom -> scom
14 | | SCIf : bexp -> scom -> scom -> scom
15 | | SCWhile : bexp -> scom -> scom
16 | | SCCons : id -> aexp -> aexp -> scom
17 | | SCLookup : id -> aexp -> scom
18 | | SCMutation : aexp -> aexp -> scom
19 | | SCDispose : aexp -> scom.
20 |
21 | (* Program states, which is called sstate *)
22 | Definition store := id -> nat.
23 |
24 | (* if heap maps a natural number (address) to
25 | None, we say the address is not a valid address,
26 | or it is not in the domain of the heap *)
27 | Definition heap := nat -> option nat.
28 |
29 | Axiom finite_heap : forall h: heap, exists n: nat,
30 | forall n' v: nat, h n' = Some v -> n' < n.
31 |
32 | Axiom functional_extensionality : forall {X Y: Type} {f g : X -> Y},
33 | (forall (x: X), f x = g x) -> f = g.
34 |
35 | (* Define an empty heap, which contains no memory cells *)
36 | Definition emp_heap : heap :=
37 | fun (l: nat) => None.
38 |
39 | Definition in_dom (l: nat) (h: heap) : Prop :=
40 | exists n, h l = Some n.
41 |
42 | Definition not_in_dom (l: nat) (h: heap) : Prop :=
43 | h l = None.
44 |
45 | Theorem in_not_in_dec :
46 | forall l h, {in_dom l h} + {not_in_dom l h}.
47 | Proof.
48 | intros l h. unfold in_dom. unfold not_in_dom.
49 | destruct (h l).
50 | left. exists n. auto.
51 | right. auto.
52 | Defined.
53 |
54 | (* h1 and h2 have disjoint domain *)
55 | Definition disjoint (h1 h2: heap) : Prop :=
56 | forall l, not_in_dom l h1 \/ not_in_dom l h2.
57 |
58 | (* union of two heaps *)
59 | Definition h_union (h1 h2: heap) : heap :=
60 | fun l =>
61 | if (in_not_in_dec l h1) then h1 l else h2 l.
62 |
63 | (* h1 is a subset of h2 *)
64 | Definition h_subset (h1 h2: heap) : Prop :=
65 | forall l n, h1 l = Some n -> h2 l = Some n.
66 |
67 | (* store update *)
68 | Definition st_update (s: store) (x: id) (n: nat) : store :=
69 | fun x' => if eq_id_dec x x' then n else s x'.
70 |
71 | (* heap update *)
72 | Definition h_update (h: heap) (l: nat) (n: nat) : heap :=
73 | fun l' => if eq_nat_dec l l' then Some n else h l'.
74 |
75 | Definition sstate := (store * heap) %type.
76 |
77 | (* since program may abort, we extend our state
78 | definition to add a special state Abt *)
79 | Inductive ext_state : Type :=
80 | St: sstate -> ext_state (* normal state *)
81 | | Abt: ext_state. (* abort *)
82 |
83 |
84 | (* Next we define the operational semantics *)
85 |
86 | (* big-step semantics. You should change it into
87 | an inductive definition *)
88 | Inductive big_step:
89 | scom * sstate -> ext_state -> Prop :=
90 | | SE_Skip : forall sst,
91 | big_step (SCSkip, sst) (St sst)
92 | | SE_Ass : forall st h a1 n x,
93 | aeval st a1 = n ->
94 | big_step (SCAss x a1, (st, h)) (St (st_update st x n, h))
95 | | SE_Seq : forall c1 c2 sst sst' est,
96 | big_step (c1, sst) (St sst') ->
97 | big_step (c2, sst') est ->
98 | big_step (SCSeq c1 c2, sst) est
99 | | SE_Seq_Ab : forall c1 c2 sst,
100 | big_step (c1, sst) Abt ->
101 | big_step (SCSeq c1 c2, sst) Abt
102 | | SE_IfTrue : forall st h b c1 c2 est,
103 | beval st b = true ->
104 | big_step (c1, (st, h)) est ->
105 | big_step (SCIf b c1 c2, (st, h)) est
106 | | SE_IfFalse : forall st h b c1 c2 est,
107 | beval st b = false ->
108 | big_step (c2, (st, h)) est ->
109 | big_step (SCIf b c1 c2, (st, h)) est
110 | | SE_WhileEnd : forall b st h c,
111 | beval st b = false ->
112 | big_step (SCWhile b c, (st, h)) (St (st, h))
113 | | SE_WhileLoop : forall st h est b c,
114 | beval st b = true ->
115 | big_step (SCSeq c (SCWhile b c), (st, h)) est ->
116 | big_step (SCWhile b c, (st, h)) est
117 | | SE_Cons : forall st h a1 a2 n1 n2 x l,
118 | aeval st a1 = n1 ->
119 | aeval st a2 = n2 ->
120 | h l = None ->
121 | h (l + 1) = None ->
122 | big_step (SCCons x a1 a2, (st, h))
123 | (St (st_update st x l,
124 | h_update (h_update h (l + 1) n2) l n1))
125 | | SE_Lookup : forall st h x a1 n1 n2,
126 | aeval st a1 = n1 ->
127 | h n1 = Some n2 ->
128 | big_step (SCLookup x a1, (st, h)) (St (st_update st x n2, h))
129 | | SE_Lookup_Ab : forall st a1 n1 h x,
130 | aeval st a1 = n1 ->
131 | h n1 = None ->
132 | big_step (SCLookup x a1, (st, h)) Abt
133 | | SE_Mutation : forall st h a1 a2 n1 n2,
134 | aeval st a1 = n1 ->
135 | aeval st a2 = n2 ->
136 | in_dom n1 h ->
137 | big_step (SCMutation a1 a2, (st, h)) (St (st, h_update h n1 n2))
138 | | SE_Mutation_Ab : forall st h a1 a2 n1,
139 | aeval st a1 = n1 ->
140 | h n1 = None ->
141 | big_step (SCMutation a1 a2, (st, h)) Abt
142 | | SE_Dispose : forall st h a1 n1,
143 | aeval st a1 = n1 ->
144 | in_dom n1 h ->
145 | big_step
146 | (SCDispose a1, (st, h))
147 | (St (st, fun x => if eq_nat_dec x n1 then None else h x))
148 | | SE_Dispose_Ab : forall st h a1 n1,
149 | aeval st a1 = n1 ->
150 | h n1 = None ->
151 | big_step (SCDispose a1, (st, h)) Abt.
152 |
153 | (* small-step semantics. Should be inductive too *)
154 | Inductive small_step:
155 | scom * ext_state -> scom * ext_state -> Prop :=
156 | | S_Ass : forall st h a n x,
157 | aeval st a = n ->
158 | small_step (SCAss x a, St (st, h))
159 | (SCSkip, St (st_update st x n, h))
160 | | S_SeqStep : forall c1 c1' est est' c2,
161 | small_step (c1, est) (c1', est') ->
162 | small_step (SCSeq c1 c2, est) (SCSeq c1' c2, est')
163 | | S_SeqFinish : forall c2 est,
164 | small_step (SCSeq SCSkip c2, est) (c2, est)
165 | | S_IfTrue : forall st h b c1 c2,
166 | beval st b = true ->
167 | small_step (SCIf b c1 c2, St (st, h)) (c1, St (st, h))
168 | | S_IfFalse : forall st h b c1 c2,
169 | beval st b = false ->
170 | small_step (SCIf b c1 c2, St (st, h)) (c2, St (st, h))
171 | | S_WhileEnd : forall st h b c,
172 | beval st b = false ->
173 | small_step (SCWhile b c, St (st, h)) (SCSkip, St (st, h))
174 | | S_WhileLoop : forall st h b c,
175 | beval st b = true ->
176 | small_step (SCWhile b c, St (st, h))
177 | (SCSeq c (SCWhile b c), St (st, h))
178 | | S_Cons : forall st h x a1 a2 n1 n2 l,
179 | aeval st a1 = n1 ->
180 | aeval st a2 = n2 ->
181 | h l = None ->
182 | h (l + 1) = None ->
183 | small_step (SCCons x a1 a2, St (st, h))
184 | (SCSkip, St (st_update st x l,
185 | h_update (h_update h l n1)
186 | (l + 1) n2))
187 | | S_Lookup : forall st h x a1 n,
188 | h (aeval st a1) = Some n ->
189 | small_step (SCLookup x a1, St (st, h))
190 | (SCSkip, St (st_update st x n, h))
191 | | S_Lookup_Ab : forall st h x a1 n1,
192 | aeval st a1 = n1 ->
193 | h n1 = None ->
194 | small_step (SCLookup x a1, St (st, h))
195 | (SCSkip, Abt)
196 | | S_Mutation : forall st h a1 a2 n1 n2,
197 | aeval st a1 = n1 ->
198 | aeval st a2 = n2 ->
199 | in_dom n1 h ->
200 | small_step (SCMutation a1 a2, St (st, h))
201 | (SCSkip, St (st, h_update h n1 n2))
202 | | S_Mutation_Ab : forall st h a1 a2 n1,
203 | aeval st a1 = n1 ->
204 | h n1 = None ->
205 | small_step (SCMutation a1 a2, St (st, h))
206 | (SCSkip, Abt)
207 | | S_Dispose : forall st h a1 n1,
208 | aeval st a1 = n1 ->
209 | in_dom n1 h ->
210 | small_step
211 | (SCDispose a1, St (st, h))
212 | (SCSkip, St
213 | (st, fun x => if eq_nat_dec x n1 then None else h x))
214 | | S_Dispose_Ab : forall st h a1 n1,
215 | aeval st a1 = n1 ->
216 | h n1 = None ->
217 | small_step (SCDispose a1, St (st, h))
218 | (SCSkip, Abt).
219 |
220 | Hint Constructors small_step.
221 |
222 | (** Assertions **)
223 | Definition sass := sstate -> Prop.
224 |
225 | (* define semantics of assertion emp *)
226 | Definition emp : sass :=
227 | fun st: sstate =>
228 | snd st = emp_heap.
229 |
230 | (* assertion e1 |-> e2 *)
231 | Definition pto (e1 e2: aexp) : sass :=
232 | fun st: sstate =>
233 | match st with
234 | | (s, h) => h = h_update emp_heap (aeval s e1) (aeval s e2)
235 | end.
236 | Notation "e1 '|->' e2" := (pto e1 e2) (at level 60).
237 |
238 | (* p * q *)
239 | Definition star (p q : sass) : sass :=
240 | fun st: sstate =>
241 | match st with
242 | | (s, h) =>
243 | exists h1, exists h2,
244 | disjoint h1 h2 /\ h_union h1 h2 = h /\ p (s, h1) /\ q (s, h2)
245 | end.
246 | Notation "p '**' q" := (star p q) (at level 70).
247 |
248 | (* p --* q *)
249 | Definition simp (p q: sass) : sass :=
250 | fun (st : sstate) =>
251 | match st with
252 | | (s, h) =>
253 | forall h', disjoint h' h -> p (s, h') -> q (s, h_union h h')
254 | end.
255 | Notation "p '--*' q" := (simp p q) (at level 80).
256 |
257 |
258 | Definition pure (p: sass) : Prop :=
259 | forall s h1 h2, p (s, h1) -> p (s, h2).
260 |
261 | Definition precise (p: sass) : Prop :=
262 | forall h h1 h2 s,
263 | h_subset h1 h
264 | -> h_subset h2 h
265 | -> p (s, h1)
266 | -> p (s, h2)
267 | -> h1 = h2.
268 |
269 | Definition intuitionistic (p: sass) : Prop :=
270 | forall s h h', p (s, h) -> disjoint h h' -> p (s, h_union h h').
271 |
272 |
273 | (* continue here *)
274 |
275 | Definition s_conj (p q: sass) : sass :=
276 | fun (s: sstate) => p s /\ q s.
277 | Notation "p '//\\' q" := (s_conj p q) (at level 75).
278 |
279 | Definition s_disj (p q: sass) : sass :=
280 | fun (s: sstate) => p s \/ q s.
281 | Notation "p '\\//' q" := (s_disj p q) (at level 78).
282 |
283 | Definition s_imp (p q: sass) : sass :=
284 | fun (s: sstate) => p s -> q s.
285 | Notation "p '~~>' q" := (s_imp p q) (at level 85).
286 |
287 | Definition strongerThan (p q: sass) : Prop :=
288 | forall s: sstate, s_imp p q s.
289 | Notation "p '==>' q" := (strongerThan p q) (at level 90).
290 |
291 | Definition spEquiv (p q: sass) : Prop :=
292 | (p ==> q) /\ (q ==> p).
293 | Notation "p '<==>' q" := (spEquiv p q) (at level 90).
294 |
295 | (* Prove the following lemmas *)
296 | Lemma disj_star_distr: forall (p q r: sass),
297 | (p \\// q) ** r <==> (p ** r) \\// (q ** r).
298 | Proof.
299 | split; unfold strongerThan, s_imp; intros; destruct s.
300 | destruct H as [h1 [h2 [H1 [H2 [H3 H4]]]]].
301 | destruct H3. left. exists h1. eauto. right. exists h1. eauto.
302 | destruct H; destruct H as [h1 [h2 [H1 [H2 [H3 H4]]]]];
303 | exists h1; exists h2; repeat split; eauto.
304 | left. auto. right. auto.
305 | Qed.
306 |
307 | Lemma conj_star_distr: forall (p q r: sass),
308 | (p //\\ q) ** r ==> (p ** r) //\\ (q ** r).
309 | Proof.
310 | unfold strongerThan, s_imp. intros. destruct s.
311 | destruct H as [h1 [h2 [H1 [H2 [H3 H4]]]]]. destruct H3.
312 | split; exists h1; exists h2; eauto.
313 | Qed.
314 |
315 | Lemma h_union_subst:
316 | forall h1 h2 h, h_union h1 h2 = h ->
317 | disjoint h1 h2 ->
318 | h_subset h2 h.
319 | Proof.
320 | unfold h_subset, h_union. intros;
321 | subst; destruct (in_not_in_dec l h1); auto.
322 | destruct (H0 l); destruct i; unfold not_in_dom in H;
323 | congruence.
324 | Qed.
325 |
326 | Lemma h_union_determ:
327 | forall h1 h1' h2, h_union h1 h2 = h_union h1' h2 ->
328 | disjoint h1 h2 ->
329 | disjoint h1' h2 ->
330 | h1 = h1'.
331 | Proof.
332 | intros.
333 | apply functional_extensionality. intros.
334 | assert ((h_union h1 h2) x = (h_union h1' h2) x). rewrite H. reflexivity.
335 | unfold h_union in H2.
336 | destruct (in_not_in_dec x h1);
337 | destruct (in_not_in_dec x h1'); eauto.
338 | destruct i. destruct (H0 x). congruence. rewrite H3 in H2. congruence.
339 | destruct i. destruct (H1 x). congruence. rewrite H3 in H2. congruence.
340 | unfold not_in_dom in *. rewrite n. rewrite n0. reflexivity.
341 | Qed.
342 |
343 | Hint Resolve h_union_subst.
344 | Hint Resolve h_union_determ.
345 |
346 | Lemma precise_conj_distr: forall (p q r: sass),
347 | precise r -> (p ** r) //\\ (q ** r) ==> (p //\\ q) ** r.
348 | Proof.
349 | unfold strongerThan, s_imp. intros. destruct s.
350 | destruct H0.
351 | destruct H0 as [h1 [h2 [H2 [H3 [H4 H5]]]]].
352 | destruct H1 as [h1' [h2' [H2' [H3' [H4' H5']]]]].
353 | unfold precise in H.
354 | assert (h2 = h2'). eapply H; eauto. subst.
355 | assert (h1 = h1'). eauto. subst.
356 | exists h1'. exists h2'. repeat split; eauto.
357 | Qed.
358 |
359 | Inductive multiStep :
360 | scom * ext_state -> scom * ext_state -> Prop :=
361 | | step0: forall c s, multiStep (c, s) (c, s)
362 | | stepn: forall c s c' s' c'' s'',
363 | small_step (c, s) (c', s')
364 | -> multiStep (c', s') (c'', s'')
365 | -> multiStep (c, s) (c'', s'').
366 |
367 | Hint Constructors multiStep.
368 |
369 | (* c is safe at state s *)
370 | Definition safeAt (c: scom) (s: sstate) : Prop :=
371 | (* ~ multiStep (c, St s) Abt *)
372 |
373 | forall c' s',
374 | multiStep (c, St s) (c', St s')
375 | -> c' = SCSkip \/ exists c'', exists s'', small_step (c', St s') (c'', St s'').
376 |
377 | Lemma small_abt: forall c c' s, small_step (c, Abt) (c', s) ->
378 | s = Abt.
379 | Proof.
380 | induction c; intros; inversion H; subst; eauto.
381 | Qed.
382 |
383 | Lemma multi_abt: forall cs cs', multiStep cs cs' ->
384 | snd cs = Abt ->
385 | snd cs' = Abt.
386 | Proof.
387 | intros. induction H. auto.
388 | destruct s. simpl in H0. inversion H0. inversion H; subst; auto.
389 | apply small_abt in H3. subst. auto.
390 | Qed.
391 |
392 | Definition safeMono (c: scom) : Prop :=
393 | forall s h h',
394 | safeAt c (s, h) -> disjoint h h' -> safeAt c (s, h_union h h').
395 |
396 | Definition frame (c: scom) : Prop :=
397 | forall s h1 h2 c' s' h',
398 | safeAt c (s, h1)
399 | -> disjoint h1 h2
400 | -> small_step (c, St (s, h_union h1 h2)) (c', St (s', h'))
401 | -> exists h1',
402 | small_step (c, St (s, h1)) (c', St (s', h1'))
403 | /\ disjoint h1' h2
404 | /\ h_union h1' h2 = h'.
405 |
406 | Lemma multistep_seq: forall cs c2 cs', multiStep cs cs' ->
407 | multiStep (SCSeq (fst cs) c2, (snd cs)) (SCSeq (fst cs') c2, (snd cs')).
408 | Proof.
409 | intros.
410 | induction H. constructor.
411 | econstructor; eauto.
412 | Qed.
413 |
414 | Lemma safeAt_seq: forall c1 c2 s h, safeAt (SCSeq c1 c2) (s, h) ->
415 | safeAt c1 (s, h).
416 | Proof.
417 | unfold safeAt. intros.
418 | assert (multiStep (SCSeq c1 c2, St (s, h)) (SCSeq c' c2, St s')).
419 | remember (c1, St (s, h)) as cs. remember (c', St s') as cs'.
420 | apply multistep_seq with (c2 := c2) in H0. subst. auto.
421 | apply H in H1. destruct H1. inversion H1. destruct H1 as [c'' [s'' H_s]].
422 | inversion H_s; subst. right. eauto. left. auto.
423 | Qed.
424 |
425 | Lemma union_none: forall h1 h2 x,
426 | h_union h1 h2 x = None ->
427 | h1 x = None /\ h2 x = None.
428 | Proof.
429 | intros. unfold h_union in *. destruct (in_not_in_dec x h1).
430 | split; auto. destruct i. congruence.
431 | split; auto.
432 | Qed.
433 |
434 | Lemma disjoint_update: forall h1 h2 x n,
435 | disjoint h1 h2 ->
436 | h2 x = None ->
437 | disjoint (h_update h1 x n) h2.
438 | Proof.
439 | unfold disjoint, not_in_dom. intros.
440 | unfold h_update. destruct (eq_nat_dec x l). subst.
441 | auto. auto.
442 | Qed.
443 |
444 | Hint Resolve disjoint_update.
445 |
446 | Lemma union_update: forall h1 h2 x n,
447 | h_union (h_update h1 x n) h2 =
448 | h_update (h_union h1 h2) x n.
449 | Proof.
450 | intros. apply functional_extensionality. intros.
451 | unfold h_union, h_update.
452 | destruct (in_not_in_dec x0). destruct i.
453 | destruct (eq_nat_dec x x0). auto.
454 | destruct (in_not_in_dec x0 h1). reflexivity. congruence.
455 | unfold not_in_dom in n0. destruct (eq_nat_dec x x0). congruence.
456 | destruct (in_not_in_dec x0 h1). destruct i. congruence. reflexivity.
457 | Qed.
458 |
459 | Lemma update_disjoint: forall h1 h2 x n,
460 | disjoint h1 h2 ->
461 | in_dom x h1 ->
462 | disjoint (h_update h1 x n) h2.
463 | Proof.
464 | unfold in_dom, h_update, disjoint, not_in_dom. intros.
465 | destruct (eq_nat_dec x l). subst. destruct H0. destruct (H l).
466 | congruence. auto. auto.
467 | Qed.
468 |
469 | Hint Resolve update_disjoint.
470 |
471 | Lemma locality_frame: forall c : scom, frame c.
472 | Proof with eauto.
473 | unfold frame. induction c; intros; inversion H1; subst; try solve [exists h1; eauto].
474 | Case "Seq".
475 | apply safeAt_seq in H.
476 | eapply IHc1 in H... destruct H as [h'' [H5 [H6 H7]]].
477 | exists h''. eauto.
478 | Case "Cons".
479 | exists (h_update (h_update h1 l (aeval s a)) (l + 1) (aeval s a0)).
480 | destruct (union_none h1 h2 l H12).
481 | destruct (union_none h1 h2 (l+1) H13).
482 | repeat split. constructor... eapply disjoint_update...
483 | rewrite union_update. rewrite union_update. reflexivity.
484 | Case "Lookup".
485 | assert (multiStep (SCLookup i a, St (s, h1)) (SCLookup i a, St (s, h1))).
486 | constructor. apply H in H2. destruct H2. inversion H2.
487 | destruct H2 as [c'' [s'' H_s]]. inversion H_s; subst.
488 | exists h1. repeat split... unfold h_union in H3.
489 | destruct (in_not_in_dec (aeval s a) h1). rewrite H3 in H4.
490 | inversion H4; subst... congruence.
491 | Case "Mutation".
492 | assert (multiStep (SCMutation a a0, St (s', h1)) (SCMutation a a0, St (s', h1))).
493 | constructor. apply H in H2. destruct H2. inversion H2.
494 | destruct H2 as [c'' [s'' H_s]]. inversion H_s; subst.
495 | exists (h_update h1 (aeval s' a) (aeval s' a0)).
496 | repeat split... rewrite union_update...
497 | Case "Dispose".
498 | assert (multiStep (SCDispose a, St (s', h1)) (SCDispose a, St (s', h1))).
499 | constructor. apply H in H2. destruct H2. inversion H2.
500 | destruct H2 as [c'' [s'' H_s]]. inversion H_s; subst.
501 | exists (fun x => if eq_nat_dec x (aeval s' a) then None else h1 x).
502 | repeat split... unfold disjoint, not_in_dom. intros.
503 | destruct (eq_nat_dec l (aeval s' a))...
504 | apply functional_extensionality. intros.
505 | unfold h_union. destruct (in_not_in_dec x)...
506 | destruct i. destruct (eq_nat_dec x (aeval s' a))...
507 | destruct (in_not_in_dec x h1)... congruence.
508 | unfold not_in_dom in n. destruct (eq_nat_dec x (aeval s' a)).
509 | subst. destruct (H0 (aeval s' a))... destruct H8. congruence.
510 | destruct (in_not_in_dec x h1)... destruct i. congruence.
511 | Qed.
512 |
513 | Lemma small_union: forall c s h c' s' h' h1,
514 | small_step (c, St (s, h)) (c', St (s', h')) ->
515 | disjoint h h1 ->
516 | exists c'', exists sh',
517 | small_step (c, St (s, h_union h h1)) (c'', St sh').
518 | Proof with eauto.
519 | induction c; intros; inversion H; subst;
520 | try solve [exists c'; eauto]; try solve [exists SCSkip; eauto].
521 | exists SCSkip. exists (st_update s i (aeval s a), h_union h' h1)...
522 | destruct (IHc1 s h c1' s' h' h1 H2 H0) as [c'' [sh' H_s]].
523 | exists (SCSeq c'' c2)...
524 | exists (SCSeq c (SCWhile b c))...
525 | Case "Cons".
526 | destruct (finite_heap (h_union h h1)) as [l' H_h].
527 | assert (h_union h h1 l' = None). destruct (in_not_in_dec l' (h_union h h1))...
528 | destruct i0. apply H_h in H1. omega.
529 | assert (h_union h h1 (l'+1)= None). destruct (in_not_in_dec (l'+1) (h_union h h1))...
530 | destruct i0. apply H_h in H2. omega.
531 | exists SCSkip. exists (st_update s i l',
532 | h_update (h_update (h_union h h1) l' (aeval s a))
533 | (l'+1) (aeval s a0))...
534 | Case "Lookup".
535 | exists SCSkip. exists (st_update s i n, h_union h' h1).
536 | constructor. unfold h_union. destruct (in_not_in_dec (aeval s a) h')...
537 | congruence.
538 | Case "Mutation".
539 | exists SCSkip. exists (s', h_update (h_union h h1) (aeval s' a) (aeval s' a0)).
540 | constructor... destruct H10. exists x... unfold h_union.
541 | destruct (in_not_in_dec (aeval s' a) h)... congruence.
542 | Case "Dispose".
543 | exists SCSkip. exists (s', fun x =>
544 | if eq_nat_dec x (aeval s' a) then None else (h_union h h1 x)).
545 | constructor... destruct H8. exists x. unfold h_union.
546 | destruct (in_not_in_dec (aeval s' a) h)... congruence.
547 | Qed.
548 |
549 | Lemma safeAt_continues:
550 | forall c c' s s' h h',
551 | safeAt c (s, h) -> small_step (c, St (s, h)) (c', St (s', h')) ->
552 | safeAt c' (s', h').
553 | Proof.
554 | intros. unfold safeAt. intros.
555 | assert (multiStep (c, St (s, h)) (c'0, St s'0)). econstructor; eauto.
556 | apply H in H2. auto.
557 | Qed.
558 |
559 | Lemma locality_safeMono: forall c : scom, safeMono c.
560 | Proof with eauto.
561 | unfold safeMono. intros.
562 | unfold safeAt. intros.
563 | remember (c, St (s, h_union h h')) as cs.
564 | remember (c', St s') as cs'.
565 | generalize dependent c.
566 | generalize dependent s.
567 | generalize dependent h.
568 | induction H1; intros; inversion Heqcs; subst; inversion Heqcs'; subst;
569 | clear Heqcs; clear Heqcs'.
570 | assert (multiStep (c', St (s0, h)) (c', St (s0, h)))...
571 | apply H in H1. destruct H1... destruct H1 as [c'' [s'' H_s]].
572 | destruct s''. eapply small_union in H_s...
573 | assert (frame c0). apply locality_frame.
574 | destruct s'0. destruct s.
575 | destruct (H3 s0 h h' c'0 s h0)... destruct H4 as [H41 [H42 H43]].
576 | assert ((c', St s') = (c', St s'))...
577 | eapply IHmultiStep in H4...
578 | eapply safeAt_continues in H2... rewrite H43...
579 | apply multi_abt in H1... inversion H1.
580 | Qed.
581 |
582 | Lemma not_safe : ~ safeMono (SCCons X (ANum 1) (ANum 1)).
583 | Proof.
584 | intro H. unfold safeMono in H.
585 | assert (safeAt (SCCons X (ANum 1) (ANum 1)) (fun id => 0, emp_heap)).
586 | unfold safeAt. intros. inversion H0; subst. right.
587 | exists SCSkip.
588 | exists (st_update (fun id => 0) X 1, h_update (h_update emp_heap 1 1) 2 1).
589 | econstructor; eauto. inversion H4; subst. inversion H6; subst; auto.
590 | inversion H5.
591 | assert (disjoint emp_heap (fun n => Some 1)).
592 | unfold disjoint, not_in_dom. intros. left. reflexivity.
593 | assert (h_union emp_heap (fun n => Some 1) = fun n => Some 1). reflexivity.
594 | eapply H in H0; eauto. rewrite H2 in *.
595 | unfold safeAt in H0.
596 | assert (multiStep (SCCons X (ANum 1) (ANum 1), St (fun _ => 0, fun _ => Some 1))
597 | (SCCons X (ANum 1) (ANum 1), St (fun _ => 0, fun _ => Some 1))). constructor.
598 | apply H0 in H3. destruct H3. inversion H3.
599 | destruct H3 as [c'' [s'' H_s]].
600 | inversion H_s. inversion H12.
601 | Qed.
602 |
603 |
604 | Theorem locality: forall c : scom, safeMono c /\ frame c.
605 | Proof.
606 | split. apply locality_safeMono. apply locality_frame.
607 | Qed.
--------------------------------------------------------------------------------
/SfLib.v:
--------------------------------------------------------------------------------
1 | (** * SfLib: Software Foundations Library *)
2 |
3 | (** Here we collect together several useful definitions and theorems
4 | from Basics.v, List.v, Poly.v, Ind.v, and Logic.v that are not
5 | already in the Coq standard library. From now on we can [Import]
6 | or [Export] this file, instead of cluttering our environment with
7 | all the examples and false starts in those files. *)
8 |
9 | (** * From the Coq Standard Library *)
10 |
11 | Require Omega. (* needed for using the [omega] tactic *)
12 | Require Export Bool.
13 | Require Export List.
14 | Export ListNotations.
15 | Require Export Arith.
16 | Require Export Arith.EqNat. (* Contains [beq_nat], among other things *)
17 |
18 | (** * From Basics.v *)
19 |
20 | Definition admit {T: Type} : T. Admitted.
21 |
22 | Require String. Open Scope string_scope.
23 |
24 | Ltac move_to_top x :=
25 | match reverse goal with
26 | | H : _ |- _ => try move x after H
27 | end.
28 |
29 | Tactic Notation "assert_eq" ident(x) constr(v) :=
30 | let H := fresh in
31 | assert (x = v) as H by reflexivity;
32 | clear H.
33 |
34 | Tactic Notation "Case_aux" ident(x) constr(name) :=
35 | first [
36 | set (x := name); move_to_top x
37 | | assert_eq x name; move_to_top x
38 | | fail 1 "because we are working on a different case" ].
39 |
40 | Tactic Notation "Case" constr(name) := Case_aux Case name.
41 | Tactic Notation "SCase" constr(name) := Case_aux SCase name.
42 | Tactic Notation "SSCase" constr(name) := Case_aux SSCase name.
43 | Tactic Notation "SSSCase" constr(name) := Case_aux SSSCase name.
44 | Tactic Notation "SSSSCase" constr(name) := Case_aux SSSSCase name.
45 | Tactic Notation "SSSSSCase" constr(name) := Case_aux SSSSSCase name.
46 | Tactic Notation "SSSSSSCase" constr(name) := Case_aux SSSSSSCase name.
47 | Tactic Notation "SSSSSSSCase" constr(name) := Case_aux SSSSSSSCase name.
48 |
49 | Fixpoint ble_nat (n m : nat) : bool :=
50 | match n with
51 | | O => true
52 | | S n' =>
53 | match m with
54 | | O => false
55 | | S m' => ble_nat n' m'
56 | end
57 | end.
58 |
59 | Theorem andb_true_elim1 : forall b c,
60 | andb b c = true -> b = true.
61 | Proof.
62 | intros b c H.
63 | destruct b.
64 | Case "b = true".
65 | reflexivity.
66 | Case "b = false".
67 | rewrite <- H. reflexivity. Qed.
68 |
69 | Theorem andb_true_elim2 : forall b c,
70 | andb b c = true -> c = true.
71 | Proof.
72 | (* An exercise in Basics.v *)
73 | Admitted.
74 |
75 | Theorem beq_nat_sym : forall (n m : nat),
76 | beq_nat n m = beq_nat m n.
77 | (* An exercise in Lists.v *)
78 | Admitted.
79 |
80 | (** * From Props.v *)
81 |
82 | Inductive ev : nat -> Prop :=
83 | | ev_0 : ev O
84 | | ev_SS : forall n:nat, ev n -> ev (S (S n)).
85 |
86 | (** * From Logic.v *)
87 |
88 | Theorem andb_true : forall b c,
89 | andb b c = true -> b = true /\ c = true.
90 | Proof.
91 | intros b c H.
92 | destruct b.
93 | destruct c.
94 | apply conj. reflexivity. reflexivity.
95 | inversion H.
96 | inversion H. Qed.
97 |
98 | Theorem false_beq_nat: forall n n' : nat,
99 | n <> n' ->
100 | beq_nat n n' = false.
101 | Proof.
102 | (* An exercise in Logic.v *)
103 | Admitted.
104 |
105 | Theorem ex_falso_quodlibet : forall (P:Prop),
106 | False -> P.
107 | Proof.
108 | intros P contra.
109 | inversion contra. Qed.
110 |
111 | Theorem ev_not_ev_S : forall n,
112 | ev n -> ~ ev (S n).
113 | Proof.
114 | (* An exercise in Logic.v *)
115 | Admitted.
116 |
117 | Theorem ble_nat_true : forall n m,
118 | ble_nat n m = true -> n <= m.
119 | (* An exercise in Logic.v *)
120 | Admitted.
121 |
122 | Theorem ble_nat_false : forall n m,
123 | ble_nat n m = false -> ~(n <= m).
124 | (* An exercise in Logic.v *)
125 | Admitted.
126 |
127 | Inductive appears_in (n : nat) : list nat -> Prop :=
128 | | ai_here : forall l, appears_in n (n::l)
129 | | ai_later : forall m l, appears_in n l -> appears_in n (m::l).
130 |
131 | Inductive next_nat (n:nat) : nat -> Prop :=
132 | | nn : next_nat n (S n).
133 |
134 | Inductive total_relation : nat -> nat -> Prop :=
135 | tot : forall n m : nat, total_relation n m.
136 |
137 | Inductive empty_relation : nat -> nat -> Prop := .
138 |
139 | (** * From Later Files *)
140 |
141 | Definition relation (X:Type) := X -> X -> Prop.
142 |
143 | Definition deterministic {X: Type} (R: relation X) :=
144 | forall x y1 y2 : X, R x y1 -> R x y2 -> y1 = y2.
145 |
146 | Inductive multi (X:Type) (R: relation X)
147 | : X -> X -> Prop :=
148 | | multi_refl : forall (x : X),
149 | multi X R x x
150 | | multi_step : forall (x y z : X),
151 | R x y ->
152 | multi X R y z ->
153 | multi X R x z.
154 | Implicit Arguments multi [[X]].
155 |
156 | Tactic Notation "multi_cases" tactic(first) ident(c) :=
157 | first;
158 | [ Case_aux c "multi_refl" | Case_aux c "multi_step" ].
159 |
160 | Theorem multi_R : forall (X:Type) (R:relation X) (x y : X),
161 | R x y -> multi R x y.
162 | Proof.
163 | intros X R x y r.
164 | apply multi_step with y. apply r. apply multi_refl. Qed.
165 |
166 | Theorem multi_trans :
167 | forall (X:Type) (R: relation X) (x y z : X),
168 | multi R x y ->
169 | multi R y z ->
170 | multi R x z.
171 | Proof.
172 | intros. induction H. apply H0. apply multi_step with y. apply H.
173 | apply IHmulti. apply H0.
174 | Qed.
175 |
176 | (** Identifiers and polymorphic partial maps. *)
177 |
178 | Inductive id : Type :=
179 | Id : nat -> id.
180 |
181 | Theorem eq_id_dec : forall id1 id2 : id, {id1 = id2} + {id1 <> id2}.
182 | Proof.
183 | intros id1 id2.
184 | destruct id1 as [n1]. destruct id2 as [n2].
185 | destruct (eq_nat_dec n1 n2) as [Heq | Hneq].
186 | Case "n1 = n2".
187 | left. rewrite Heq. reflexivity.
188 | Case "n1 <> n2".
189 | right. intros contra. inversion contra. apply Hneq. apply H0.
190 | Defined.
191 |
192 | Lemma eq_id : forall (T:Type) x (p q:T),
193 | (if eq_id_dec x x then p else q) = p.
194 | Proof.
195 | intros.
196 | destruct (eq_id_dec x x); try reflexivity.
197 | apply ex_falso_quodlibet; auto.
198 | Qed.
199 |
200 | Lemma neq_id : forall (T:Type) x y (p q:T), x <> y ->
201 | (if eq_id_dec x y then p else q) = q.
202 | Proof.
203 | intros. destruct (eq_id_dec x y).
204 | apply ex_falso_quodlibet. unfold not in H. apply H. apply e.
205 | reflexivity.
206 | Qed.
207 |
208 | Definition partial_map (A:Type) := id -> option A.
209 |
210 | Definition empty {A:Type} : partial_map A := (fun _ => None).
211 |
212 | Notation "'\empty'" := empty.
213 |
214 | Definition extend {A:Type} (Gamma : partial_map A) (x:id) (T : A) :=
215 | fun x' => if eq_id_dec x x' then Some T else Gamma x'.
216 |
217 | Lemma extend_eq : forall A (ctxt: partial_map A) x T,
218 | (extend ctxt x T) x = Some T.
219 | Proof.
220 | intros. unfold extend. rewrite eq_id; auto.
221 | Qed.
222 |
223 | Lemma extend_neq : forall A (ctxt: partial_map A) x1 T x2,
224 | x2 <> x1 ->
225 | (extend ctxt x2 T) x1 = ctxt x1.
226 | Proof.
227 | intros. unfold extend. rewrite neq_id; auto.
228 | Qed.
229 |
230 | Lemma extend_shadow : forall A (ctxt: partial_map A) t1 t2 x1 x2,
231 | extend (extend ctxt x2 t1) x2 t2 x1 = extend ctxt x2 t2 x1.
232 | Proof with auto.
233 | intros. unfold extend. destruct (eq_id_dec x2 x1)...
234 | Qed.
235 |
236 | (** -------------------- *)
237 |
238 | (** * Some useful tactics *)
239 |
240 | Tactic Notation "solve_by_inversion_step" tactic(t) :=
241 | match goal with
242 | | H : _ |- _ => solve [ inversion H; subst; t ]
243 | end
244 | || fail "because the goal is not solvable by inversion.".
245 |
246 | Tactic Notation "solve" "by" "inversion" "1" :=
247 | solve_by_inversion_step idtac.
248 | Tactic Notation "solve" "by" "inversion" "2" :=
249 | solve_by_inversion_step (solve by inversion 1).
250 | Tactic Notation "solve" "by" "inversion" "3" :=
251 | solve_by_inversion_step (solve by inversion 2).
252 | Tactic Notation "solve" "by" "inversion" :=
253 | solve by inversion 1.
254 |
255 | (** $Date: 2014-12-31 12:04:02 -0500 (Wed, 31 Dec 2014) $ *)
256 |
--------------------------------------------------------------------------------
/Symbols.v:
--------------------------------------------------------------------------------
1 | (** * Symbols: Special symbols *)
2 |
3 | (* This file defines some HTML symbols for use by the coqdoc
4 | preprocessor. It is not intended to be read by anybody. *)
5 |
6 | (** printing -> #→# *)
7 | (** printing || #⇓# *)
8 | (** printing ==> #⇒# *)
9 | (** printing ==>* #⇒*# *)
10 | (** printing ==>+ #⇒+# *)
11 | (** printing |- #⊢# *)
12 | (** printing <- #←# *)
13 | (** printing <-> #↔# *)
14 | (** printing forall #∀# *)
15 | (** printing exists #∃# *)
16 | (** printing /\ #∧# *)
17 | (** printing \/ #∨# *)
18 | (** printing ->> #⇾# *)
19 | (** printing <<->> #⇿# *)
20 | (** printing |- #⊢# *)
21 | (** printing Gamma #Γ# *)
22 | (** printing Gamma' #Γ'# *)
23 | (** printing Gamma'' #Γ''# *)
24 | (** printing |-> #↦# *)
25 |
26 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
27 |
28 |
--------------------------------------------------------------------------------
/Typechecking.v:
--------------------------------------------------------------------------------
1 | (** * MoreStlc: A Typechecker for STLC *)
2 |
3 | Require Export Stlc.
4 |
5 | (** The [has_type] relation of the STLC defines what it means for a
6 | term to belong to a type (in some context). But it doesn't, by
7 | itself, tell us how to _check_ whether or not a term is well
8 | typed.
9 |
10 | Fortunately, the rules defining [has_type] are _syntax directed_
11 | -- they exactly follow the shape of the term. This makes it
12 | straightforward to translate the typing rules into clauses of a
13 | typechecking _function_ that takes a term and a context and either
14 | returns the term's type or else signals that the term is not
15 | typable. *)
16 |
17 | Module STLCChecker.
18 | Import STLC.
19 |
20 | (* ###################################################################### *)
21 | (** ** Comparing Types *)
22 |
23 | (** First, we need a function to compare two types for equality... *)
24 |
25 | Fixpoint beq_ty (T1 T2:ty) : bool :=
26 | match T1,T2 with
27 | | TBool, TBool =>
28 | true
29 | | TArrow T11 T12, TArrow T21 T22 =>
30 | andb (beq_ty T11 T21) (beq_ty T12 T22)
31 | | _,_ =>
32 | false
33 | end.
34 |
35 | (** ... and we need to establish the usual two-way connection between
36 | the boolean result returned by [beq_ty] and the logical
37 | proposition that its inputs are equal. *)
38 |
39 | Lemma beq_ty_refl : forall T1,
40 | beq_ty T1 T1 = true.
41 | Proof.
42 | intros T1. induction T1; simpl.
43 | reflexivity.
44 | rewrite IHT1_1. rewrite IHT1_2. reflexivity. Qed.
45 |
46 | Lemma beq_ty__eq : forall T1 T2,
47 | beq_ty T1 T2 = true -> T1 = T2.
48 | Proof with auto.
49 | intros T1. induction T1; intros T2 Hbeq; destruct T2; inversion Hbeq.
50 | Case "T1=TBool".
51 | reflexivity.
52 | Case "T1=TArrow T1_1 T1_2".
53 | apply andb_true in H0. inversion H0 as [Hbeq1 Hbeq2].
54 | apply IHT1_1 in Hbeq1. apply IHT1_2 in Hbeq2. subst... Qed.
55 |
56 | (* ###################################################################### *)
57 | (** ** The Typechecker *)
58 |
59 | (** Now here's the typechecker. It works by walking over the
60 | structure of the given term, returning either [Some T] or [None].
61 | Each time we make a recursive call to find out the types of the
62 | subterms, we need to pattern-match on the results to make sure
63 | that they are not [None]. Also, in the [tapp] case, we use
64 | pattern matching to extract the left- and right-hand sides of the
65 | function's arrow type (and fail if the type of the function is not
66 | [TArrow T11 T12] for some [T1] and [T2]). *)
67 |
68 | Fixpoint type_check (Gamma:context) (t:tm) : option ty :=
69 | match t with
70 | | tvar x => Gamma x
71 | | tabs x T11 t12 => match type_check (extend Gamma x T11) t12 with
72 | | Some T12 => Some (TArrow T11 T12)
73 | | _ => None
74 | end
75 | | tapp t1 t2 => match type_check Gamma t1, type_check Gamma t2 with
76 | | Some (TArrow T11 T12),Some T2 =>
77 | if beq_ty T11 T2 then Some T12 else None
78 | | _,_ => None
79 | end
80 | | ttrue => Some TBool
81 | | tfalse => Some TBool
82 | | tif x t f => match type_check Gamma x with
83 | | Some TBool =>
84 | match type_check Gamma t, type_check Gamma f with
85 | | Some T1, Some T2 =>
86 | if beq_ty T1 T2 then Some T1 else None
87 | | _,_ => None
88 | end
89 | | _ => None
90 | end
91 | end.
92 |
93 | (* ###################################################################### *)
94 | (** ** Properties *)
95 |
96 | (** To verify that this typechecking algorithm is the correct one, we
97 | show that it is _sound_ and _complete_ for the original [has_type]
98 | relation -- that is, [type_check] and [has_type] define the same
99 | partial function. *)
100 |
101 | Theorem type_checking_sound : forall Gamma t T,
102 | type_check Gamma t = Some T -> has_type Gamma t T.
103 | Proof with eauto.
104 | intros Gamma t. generalize dependent Gamma.
105 | t_cases (induction t) Case; intros Gamma T Htc; inversion Htc.
106 | Case "tvar"...
107 | Case "tapp".
108 | remember (type_check Gamma t1) as TO1.
109 | remember (type_check Gamma t2) as TO2.
110 | destruct TO1 as [T1|]; try solve by inversion;
111 | destruct T1 as [|T11 T12]; try solve by inversion.
112 | destruct TO2 as [T2|]; try solve by inversion.
113 | destruct (beq_ty T11 T2) eqn: Heqb;
114 | try solve by inversion.
115 | apply beq_ty__eq in Heqb.
116 | inversion H0; subst...
117 | Case "tabs".
118 | rename i into y. rename t into T1.
119 | remember (extend Gamma y T1) as G'.
120 | remember (type_check G' t0) as TO2.
121 | destruct TO2; try solve by inversion.
122 | inversion H0; subst...
123 | Case "ttrue"...
124 | Case "tfalse"...
125 | Case "tif".
126 | remember (type_check Gamma t1) as TOc.
127 | remember (type_check Gamma t2) as TO1.
128 | remember (type_check Gamma t3) as TO2.
129 | destruct TOc as [Tc|]; try solve by inversion.
130 | destruct Tc; try solve by inversion.
131 | destruct TO1 as [T1|]; try solve by inversion.
132 | destruct TO2 as [T2|]; try solve by inversion.
133 | destruct (beq_ty T1 T2) eqn:Heqb;
134 | try solve by inversion.
135 | apply beq_ty__eq in Heqb.
136 | inversion H0. subst. subst...
137 | Qed.
138 |
139 | Theorem type_checking_complete : forall Gamma t T,
140 | has_type Gamma t T -> type_check Gamma t = Some T.
141 | Proof with auto.
142 | intros Gamma t T Hty.
143 | has_type_cases (induction Hty) Case; simpl.
144 | Case "T_Var"...
145 | Case "T_Abs". rewrite IHHty...
146 | Case "T_App".
147 | rewrite IHHty1. rewrite IHHty2.
148 | rewrite (beq_ty_refl T11)...
149 | Case "T_True"...
150 | Case "T_False"...
151 | Case "T_If". rewrite IHHty1. rewrite IHHty2.
152 | rewrite IHHty3. rewrite (beq_ty_refl T)...
153 | Qed.
154 |
155 | End STLCChecker.
156 |
157 | (** $Date: 2014-12-31 11:17:56 -0500 (Wed, 31 Dec 2014) $ *)
158 |
--------------------------------------------------------------------------------