Mercurial > cpdt > repo
comparison src/Predicates.v @ 370:549d604c3d16
Move exercises out of mainline book
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Fri, 02 Mar 2012 09:58:00 -0500 |
parents | ad315efc3b6b |
children | d1276004eec9 |
comparison
equal
deleted
inserted
replaced
369:4550dedad73a | 370:549d604c3d16 |
---|---|
985 intros; eapply propify_holds'; eauto. | 985 intros; eapply propify_holds'; eauto. |
986 Qed. | 986 Qed. |
987 (* end thide *) | 987 (* end thide *) |
988 | 988 |
989 (* end hide *) | 989 (* end hide *) |
990 | |
991 | |
992 (** * Exercises *) | |
993 | |
994 (** %\begin{enumerate}%#<ol># | |
995 | |
996 %\item%#<li># Prove these tautologies of propositional logic, using only the tactics [apply], [assumption], %\coqdockw{%#<tt>#constructor#</tt>#%}%, [destruct], [intro], [intros], %\coqdockw{%#<tt>#left#</tt>#%}%, %\coqdockw{%#<tt>#right#</tt>#%}%, [split], and [unfold]. | |
997 %\begin{enumerate}%#<ol># | |
998 %\item%#<li># [(][True \/ False) /\ (][False \/ True)]#</li># | |
999 %\item%#<li># [P -> ~ ~ P]#</li># | |
1000 %\item%#<li># [P /\ (][Q \/ R) -> (][P /\ Q) \/ (][P /\ R)]#</li># | |
1001 #</ol> </li>#%\end{enumerate}% | |
1002 | |
1003 %\item%#<li># Prove the following tautology of first-order logic, using only the tactics [apply], [assert], [assumption], [destruct], [eapply], %\coqdockw{%#<tt>#eassumption#</tt>#%}%, and %\coqdockw{%#<tt>#exists#</tt>#%}%. You will probably find the [assert] tactic useful for stating and proving an intermediate lemma, enabling a kind of %``%#"#forward reasoning,#"#%''% in contrast to the %``%#"#backward reasoning#"#%''% that is the default for Coq tactics. The tactic %\coqdockw{%#<tt>#eassumption#</tt>#%}% is a version of [assumption] that will do matching of unification variables. Let some variable [T] of type [Set] be the set of individuals. [x] is a constant symbol, [p] is a unary predicate symbol, [q] is a binary predicate symbol, and [f] is a unary function symbol. | |
1004 %\begin{enumerate}%#<ol># | |
1005 %\item%#<li># [p x -> (][forall x, p x -> exists y, q x y) -> (][forall x y, q x y -> q y (f y)) -> exists z, q z (f z)]#</li># | |
1006 #</ol> </li>#%\end{enumerate}% | |
1007 | |
1008 %\item%#<li># Define an inductive predicate capturing when a natural number is an integer multiple of either 6 or 10. Prove that 13 does not satisfy your predicate, and prove that any number satisfying the predicate is not odd. It is probably easiest to prove the second theorem by indicating %``%#"#odd-ness#"#%''% as equality to [2 * n + 1] for some [n].#</li># | |
1009 | |
1010 %\item%#<li># $\star$ Define a simple programming language, its semantics, and its typing rules, and then prove that well-typed programs cannot go wrong. Specifically: | |
1011 %\begin{enumerate}%#<ol># | |
1012 %\item%#<li># Define [var] as a synonym for the natural numbers.#</li># | |
1013 %\item%#<li># Define an inductive type [exp] of expressions, containing natural number constants, natural number addition, pairing of two other expressions, extraction of the first component of a pair, extraction of the second component of a pair, and variables (based on the [var] type you defined).#</li># | |
1014 %\item%#<li># Define an inductive type [cmd] of commands, containing expressions and variable assignments. A variable assignment node should contain the variable being assigned, the expression being assigned to it, and the command to run afterward.#</li># | |
1015 %\item%#<li># Define an inductive type [val] of values, containing natural number constants and pairings of values.#</li># | |
1016 %\item%#<li># Define a type of variable assignments, which assign a value to each variable.#</li># | |
1017 %\item%#<li># Define a big-step evaluation relation [eval], capturing what it means for an expression to evaluate to a value under a particular variable assignment. %``%#"#Big step#"#%''% means that the evaluation of every expression should be proved with a single instance of the inductive predicate you will define. For instance, %``%#"#[1 + 1] evaluates to [2] under assignment [va]#"#%''% should be derivable for any assignment [va].#</li># | |
1018 %\item%#<li># Define a big-step evaluation relation [run], capturing what it means for a command to run to a value under a particular variable assignment. The value of a command is the result of evaluating its final expression.#</li># | |
1019 %\item%#<li># Define a type of variable typings, which are like variable assignments, but map variables to types instead of values. You might use polymorphism to share some code with your variable assignments.#</li># | |
1020 %\item%#<li># Define typing judgments for expressions, values, and commands. The expression and command cases will be in terms of a typing assignment.#</li># | |
1021 %\item%#<li># Define a predicate [varsType] to express when a variable assignment and a variable typing agree on the types of variables.#</li># | |
1022 %\item%#<li># Prove that any expression that has type [t] under variable typing [vt] evaluates under variable assignment [va] to some value that also has type [t] in [vt], as long as [va] and [vt] agree.#</li># | |
1023 %\item%#<li># Prove that any command that has type [t] under variable typing [vt] evaluates under variable assignment [va] to some value that also has type [t] in [vt], as long as [va] and [vt] agree.#</li># | |
1024 #</ol> </li>#%\end{enumerate}% | |
1025 A few hints that may be helpful: | |
1026 %\begin{enumerate}%#<ol># | |
1027 %\item%#<li># One easy way of defining variable assignments and typings is to define both as instances of a polymorphic map type. The map type at parameter [T] can be defined to be the type of arbitrary functions from variables to [T]. A helpful function for implementing insertion into such a functional map is [eq_nat_dec], which you can make available with [Require Import Arith.]. [eq_nat_dec] has a dependent type that tells you that it makes accurate decisions on whether two natural numbers are equal, but you can use it as if it returned a boolean, e.g., [if eq_nat_dec n m then E1 else E2].#</li># | |
1028 %\item%#<li># If you follow the last hint, you may find yourself writing a proof that involves an expression with [eq_nat_dec] that you would like to simplify. Running [destruct] on the particular call to [eq_nat_dec] should do the trick. You can automate this advice with a piece of Ltac: [[ | |
1029 match goal with | |
1030 | [ |- context[eq_nat_dec ?X ?Y] ] => destruct (eq_nat_dec X Y) | |
1031 end | |
1032 ]] | |
1033 #</li># | |
1034 %\item%#<li># You probably do not want to use an inductive definition for compatibility of variable assignments and typings.#</li># | |
1035 %\item%#<li># The [CpdtTactics] module from this book contains a variant [crush'] of [crush]. [crush'] takes two arguments. The first argument is a list of lemmas and other functions to be tried automatically in %``%#"#forward reasoning#"#%''% style, where we add new facts without being sure yet that they link into a proof of the conclusion. The second argument is a list of predicates on which inversion should be attempted automatically. For instance, running [crush' (lemma1, lemma2) pred] will search for chances to apply [lemma1] and [lemma2] to hypotheses that are already available, adding the new concluded fact if suitable hypotheses can be found. Inversion will be attempted on any hypothesis using [pred], but only those inversions that narrow the field of possibilities to one possible rule will be kept. The format of the list arguments to [crush'] is that you can pass an empty list as [tt], a singleton list as the unadorned single element, and a multiple-element list as a tuple of the elements.#</li># | |
1036 %\item%#<li># If you want [crush'] to apply polymorphic lemmas, you may have to do a little extra work, if the type parameter is not a free variable of your proof context (so that [crush'] does not know to try it). For instance, if you define a polymorphic map insert function [assign] of some type [forall T : Set, ...], and you want particular applications of [assign] added automatically with type parameter [U], you would need to include [assign] in the lemma list as [assign U] (if you have implicit arguments off) or [assign (T := U)] or [@assign U] (if you have implicit arguments on).#</li># | |
1037 #</ol> </li>#%\end{enumerate}% | |
1038 | |
1039 #</li># | |
1040 | |
1041 #</ol>#%\end{enumerate}% *) |