(** * IndProp: Inductively Defined Propositions *)
Set Warnings "-notation-overridden,-parsing".
Require Export Logic.
Require Coq.omega.Omega.
(* ################################################################# *)
(** * Inductively Defined Propositions *)
(** In the [Logic] chapter, we looked at several ways of writing propositions, including conjunction, disjunction, and quantifiers. In this chapter, we bring a new tool into the mix: _inductive definitions_.  Recall that we have seen two ways of stating that a number [n] is even: We can say (1) [evenb n = true], or (2) [exists k, n = double k].  Yet another possibility is to say that [n] is even if we can establish its evenness from the following rules:  - Rule [ev_0]:  The number [0] is even. - Rule [ev_SS]: If [n] is even, then [S (S n)] is even. *)
(** To illustrate how this definition of evenness works, let's imagine using it to show that [4] is even. By rule [ev_SS], it suffices to show that [2] is even. This, in turn, is again guaranteed by rule [ev_SS], as long as we can show that [0] is even. But this last fact follows directly from the [ev_0] rule. *)
(** We will see many definitions like this one during the rest of the course.  For purposes of informal discussions, it is helpful to have a lightweight notation that makes them easy to read and write.  _Inference rules_ are one such notation: *)
(**  ------------                        (ev_0) ev 0  ev n --------------                      (ev_SS) ev (S (S n)) *)
(** Each of the textual rules above is reformatted here as an inference rule; the intended reading is that, if the _premises_ above the line all hold, then the _conclusion_ below the line follows.  For example, the rule [ev_SS] says that, if [n] satisfies [ev], then [S (S n)] also does.  If a rule has no premises above the line, then its conclusion holds unconditionally.  We can represent a proof using these rules by combining rule applications into a _proof tree_. Here's how we might transcribe the above proof that [4] is even: *)
(**  ------  (ev_0) ev 0 ------ (ev_SS) ev 2 ------ (ev_SS) ev 4 *)
(** Why call this a "tree" (rather than a "stack", for example)? Because, in general, inference rules can have multiple premises. We will see examples of this below. *)
(** Putting all of this together, we can translate the definition of evenness into a formal Coq definition using an [Inductive] declaration, where each constructor corresponds to an inference rule: *)
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).
(** This definition is different in one crucial respect from previous uses of [Inductive]: its result is not a [Type], but rather a function from [nat] to [Prop] -- that is, a property of numbers.  Note that we've already seen other inductive definitions that result in functions, such as [list], whose type is [Type -> Type].  What is new here is that, because the [nat] argument of [ev] appears _unnamed_, to the _right_ of the colon, it is allowed to take different values in the types of different constructors: [0] in the type of [ev_0] and [S (S n)] in the type of [ev_SS].  In contrast, the definition of [list] names the [X] parameter _globally_, to the _left_ of the colon, forcing the result of [nil] and [cons] to be the same ([list X]).  Had we tried to bring [nat] to the left in defining [ev], we would have seen an error: *)
Fail Inductive wrong_ev (n : nat) : Prop :=
| wrong_ev_0 : wrong_ev 0
| wrong_ev_SS : forall n, wrong_ev n -> wrong_ev (S (S n)).
(* ===> Error: A parameter of an inductive type n is not allowed to be used as a bound variable in the type of its constructor. *)
(** ("Parameter" here is Coq jargon for an argument on the left of the colon in an [Inductive] definition; "index" is used to refer to arguments on the right of the colon.) *)
(** We can think of the definition of [ev] as defining a Coq property [ev : nat -> Prop], together with theorems [ev_0 : ev 0] and [ev_SS : forall n, ev n -> ev (S (S n))].  Such "constructor theorems" have the same status as proven theorems.  In particular, we can use Coq's [apply] tactic with the rule names to prove [ev] for particular numbers... *)
(** More generally, we can show that any number multiplied by 2 is even: *)
(** By using [inversion], we can also apply the principle of explosion to "obviously contradictory" hypotheses involving inductive properties. For example: *)
(* ================================================================= *)
(** ** Induction on Evidence *)
(** If this looks familiar, it is no coincidence: We've encountered similar problems in the [Induction] chapter, when trying to use case analysis to prove results that required induction.  And once again the solution is... induction!  The behavior of [induction] on evidence is the same as its behavior on data: It causes Coq to generate one subgoal for each constructor that could have used to build that evidence, while providing an induction hypotheses for each recursive occurrence of the property in question. *)
(** Let's try our current lemma again: *)
(** Here, we can see that Coq produced an [IH] that corresponds to [E'], the single recursive occurrence of [ev] in its own definition.  Since [E'] mentions [n'], the induction hypothesis talks about [n'], as opposed to [n] or some other number. *)
(** The equivalence between the second and third definitions of evenness now follows. *)
(** As we will see in later chapters, induction on evidence is a recurring technique across many areas, and in particular when formalizing the semantics of programming languages, where many properties of interest are defined inductively. *)
(** The following exercises provide simple examples of this technique, to help you familiarize yourself with it. *)
Example reg_exp_ex2 : [1; 2] =~ App (Char 1) (Char 2).
(** (Notice how the last example applies [MApp] to the strings [[1]] and [[2]] directly.  Since the goal mentions [[1; 2]] instead of [[1] ++ [2]], Coq wouldn't be able to figure out how to split the string on its own.)  Using [inversion], we can also show that certain strings do _not_ match a regular expression: *)
Example reg_exp_ex3 : ~ ([1; 2] =~ Char 1).
(** We can define helper functions to help write down regular expressions. The [reg_exp_of_list] function constructs a regular expression that matches exactly the list that it receives as an argument: *)
Fixpoint reg_exp_of_list {T} (l : list T) :=
match l with
| [] => EmptyStr
| x :: l' => App (Char x) (reg_exp_of_list l')
end.
Example reg_exp_ex4 : [1; 2; 3] =~ reg_exp_of_list [1; 2; 3].
(** We can also prove general facts about [exp_match].  For instance, the following lemma shows that every string [s] that matches [re] also matches [Star re]. *)
(** (Note the use of [app_nil_r] to change the goal of the theorem to exactly the same shape expected by [MStarApp].) *)
(** **** Exercise: 3 stars (exp_match_ex1)  *)
(** The following lemmas show that the informal matching rules given at the beginning of the chapter can be obtained from the formal inductive definition. *)
(** **** Exercise: 4 stars (re_not_empty)  *)
(** Write a recursive function [re_not_empty] that tests whether a regular expression matches some string. Prove that your function is correct. *)
Fixpoint re_not_empty {T : Type} (re : reg_exp T) : bool
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.  Lemma re_not_empty_correct : forall T (re : reg_exp T), (exists s, s =~ re) <-> re_not_empty re = true.  (** **** Exercise: 4 stars (exp_match_ex2)  *)
(** The [MStar''] lemma below (combined with its converse, the [MStar'] exercise above), shows that our definition of [exp_match] for [Star] is equivalent to the informal one given previously. *)
(** Now, the pumping lemma itself says that, if [s =~ re] and if the length of [s] is at least the pumping constant of [re], then [s] can be split into three substrings [s1 ++ s2 ++ s3] in such a way that [s2] can be repeated any number of times and the result, when combined with [s1] and [s3] will still match [re].  Since [s2] is also guaranteed not to be the empty string, this gives us a (constructive!) way to generate strings matching [re] that are as long as we like. *)

Lemma pumping : forall T (re : reg_exp T) s,
s =~ re ->
pumping_constant re <= length s ->
exists s1 s2 s3,
s = s1 ++ s2 ++ s3 /\
s2 <> [] /\
forall m, s1 ++ napp m s2 ++ s3 =~ re.