%\noindent%...whichcorrespondsto"proof by case analysis"inclassicalmath.Fornon-recursiveinductivetypes,thetwotacticswillalwayshaveidenticalbehavior.Oftencaseanalysisissufficient,eveninproofsaboutrecursivetypes,anditisnicetoavoidintroducingunneededinductionhypotheses.
...
...
@@ -123,7 +121,7 @@ What exactly _is_ the %\index{induction principles}%induction principle for [uni
"A/\B" := and A B : type_scope (default interpretation)
]]
*)
Print and.
(** [[
(** %\vspace{-.15in}%[[
Inductive and (A : Prop) (B : Prop) : Prop := conj : A -> B -> A /\ B
]]
%\vspace{-.1in}%
...
...
@@ -1022,7 +1006,7 @@ Section nat_tree_ind'.
(** A first attempt at writing the induction principle itself follows the intuition that nested inductive type definitions are expanded into mutual inductive definitions.
(** We begin with the tactic %\index{tactics!red}%[red], which is short for "onestepofreduction," to unfold the definition of logical negation. *)
red.
(** [[
(** %\vspace{-.15in}%[[
============================
true = false -> False
]]
The negation is replaced with an implication of falsehood. We use the tactic %\index{tactics!intro}%[intro H] to change the assumption of the implication into a hypothesis named [H]. *)
%\smallskip{}%The negation is replaced with an implication of falsehood. We use the tactic %\index{tactics!intro}%[intro H] to change the assumption of the implication into a hypothesis named [H]. *)
intro H.
(** [[
(** %\vspace{-.15in}%[[
H : true = false
============================
False
]]
This is the point in the proof where we apply some creativity. We define a function whose utility will become clear soon. *)
%\smallskip{}%This is the point in the proof where we apply some creativity. We define a function whose utility will become clear soon. *)
Definition toProp (b : bool) := if b then True else False.
(** It is worth recalling the difference between the lowercase and uppercase versions of truth and falsehood: [True] and [False] are logical propositions, while [true] and [false] are boolean values that we can case-analyze. We have defined [toProp] such that our conclusion of [False] is computationally equivalent to [toProp false]. Thus, the %\index{tactics!change}%[change] tactic will let us change the conclusion to [toProp false]. The general form [change e] replaces the conclusion with [e], whenever Coq's built-in computation rules suffice to establish the equivalence of [e] with the original conclusion. *)
change (toProp false).
(** [[
(** %\vspace{-.15in}%[[
H : true = false
============================
toProp false
]]
Now the righthand side of [H]'s equality appears in the conclusion, so we can rewrite, using the notation [<-] to request to replace the righthand side the equality with the lefthand side.%\index{tactics!rewrite}% *)
%\smallskip{}%Now the righthand side of [H]'s equality appears in the conclusion, so we can rewrite, using the notation [<-] to request to replace the righthand side the equality with the lefthand side.%\index{tactics!rewrite}% *)
rewrite <- H.
(** [[
(** %\vspace{-.15in}%[[
H : true = false
============================
toProp true
]]
We are almost done. Just how close we are to done is revealed by computational simplification. *)
%\smallskip{}%We are almost done. Just how close we are to done is revealed by computational simplification. *)