(** * Basics: Functional Programming in Coq *)

(* REMINDER:

          #####################################################
          ###  PLEASE DO NOT DISTRIBUTE SOLUTIONS PUBLICLY  ###
          #####################################################

   (See the [Preface] for why.)

*)

(* ################################################################# *)
(** * Introduction *)

(** The functional programming style is founded on simple, everyday
    mathematical intuition: If a procedure or method has no side
    effects, then (ignoring efficiency) all we need to understand
    about it is how it maps inputs to outputs -- that is, we can think
    of it as just a concrete method for computing a mathematical
    function.  This is one sense of the word "functional" in
    "functional programming."  The direct connection between programs
    and simple mathematical objects supports both formal correctness
    proofs and sound informal reasoning about program behavior.

    The other sense in which functional programming is "functional" is
    that it emphasizes the use of functions (or methods) as
    _first-class_ values -- i.e., values that can be passed as
    arguments to other functions, returned as results, included in
    data structures, etc.  The recognition that functions can be
    treated as data gives rise to a host of useful and powerful
    programming idioms.

    Other common features of functional languages include _algebraic
    data types_ and _pattern matching_, which make it easy to
    construct and manipulate rich data structures, and sophisticated
    _polymorphic type systems_ supporting abstraction and code reuse.
    Coq offers all of these features.

    The first half of this chapter introduces the most essential
    elements of Coq's functional programming language, called
    _Gallina_.  The second half introduces some basic _tactics_ that
    can be used to prove properties of Coq programs. *)

(* ################################################################# *)
(** * Enumerated Types *)

(** One notable aspect of Coq is that its set of built-in
    features is _extremely_ small.  For example, instead of providing
    the usual palette of atomic data types (booleans, integers,
    strings, etc.), Coq offers a powerful mechanism for defining new
    data types from scratch, with all these familiar types as
    instances.

    Naturally, the Coq distribution comes preloaded with an extensive
    standard library providing definitions of booleans, numbers, and
    many common data structures like lists and hash tables.  But there
    is nothing magic or primitive about these library definitions.  To
    illustrate this, we will explicitly recapitulate all the
    definitions we need in this course, rather than just getting them
    implicitly from the library. *)

(* ================================================================= *)
(** ** Days of the Week *)

(** To see how this definition mechanism works, let's start with
    a very simple example.  The following declaration tells Coq that
    we are defining a new set of data values -- a _type_. *)

Inductive day : Type :=
  | monday : day
  | tuesday : day
  | wednesday : day
  | thursday : day
  | friday : day
  | saturday : day
  | sunday : day.

(** The type is called [day], and its members are [monday],
    [tuesday], etc.  The second and following lines of the definition
    can be read "[monday] is a [day], [tuesday] is a [day], etc."

    Having defined [day], we can write functions that operate on
    days. *)

Definition next_weekday (d:day) : day :=
  match d with
  | monday    => tuesday
  | tuesday   => wednesday
  | wednesday => thursday
  | thursday  => friday
  | friday    => monday
  | saturday  => monday
  | sunday    => monday
  end.

(** One thing to note is that the argument and return types of
    this function are explicitly declared.  Like most functional
    programming languages, Coq can often figure out these types for
    itself when they are not given explicitly -- i.e., it can do _type
    inference_ -- but we'll generally include them to make reading
    easier. *)

(** Having defined a function, we should check that it works on
    some examples.  There are actually three different ways to do this
    in Coq.  First, we can use the command [Compute] to evaluate a
    compound expression involving [next_weekday]. *)

Compute (next_weekday friday).
(* ==> monday : day *)

Compute (next_weekday (next_weekday saturday)).
(* ==> tuesday : day *)

(** (We show Coq's responses in comments, but, if you have a
    computer handy, this would be an excellent moment to fire up the
    Coq interpreter under your favorite IDE -- either CoqIde or Proof
    General -- and try this for yourself.  Load this file, [Basics.v],
    from the book's Coq sources, find the above example, submit it to
    Coq, and observe the result.)

    Second, we can record what we _expect_ the result to be in the
    form of a Coq example: *)

Example test_next_weekday:
  (next_weekday (next_weekday saturday)) = tuesday.

(** This declaration does two things: it makes an
    assertion (that the second weekday after [saturday] is [tuesday]),
    and it gives the assertion a name that can be used to refer to it
    later.  Having made the assertion, we can also ask Coq to verify
    it, like this: *)

Proof. simpl. reflexivity.  Qed.

(** The details are not important for now (we'll come back to
    them in a bit), but essentially this can be read as "The assertion
    we've just made can be proved by observing that both sides of the
    equality evaluate to the same thing, after some simplification."

    Third, we can ask Coq to _extract_, from our [Definition], a
    program in some other, more conventional, programming
    language (OCaml, Scheme, or Haskell) with a high-performance
    compiler.  This facility is very interesting, since it gives us a
    way to construct _fully certified_ programs in mainstream
    languages.  Indeed, this is one of the main uses for which Coq was
    developed.  We'll come back to this topic in later chapters. *)

(* ================================================================= *)
(** ** Booleans *)

(** In a similar way, we can define the standard type [bool] of
    booleans, with members [true] and [false]. *)

Inductive bool : Type :=
  | true : bool
  | false : bool.

(** Although we are rolling our own booleans here for the sake
    of building up everything from scratch, Coq does, of course,
    provide a default implementation of the booleans, together with a
    multitude of useful functions and lemmas.  (Take a look at
    [Coq.Init.Datatypes] in the Coq library documentation if you're
    interested.)  Whenever possible, we'll name our own definitions
    and theorems so that they exactly coincide with the ones in the
    standard library.

    Functions over booleans can be defined in the same way as
    above: *)

Definition negb (b:bool) : bool :=
  match b with
  | true => false
  | false => true
  end.

Definition andb (b1:bool) (b2:bool) : bool :=
  match b1 with
  | true => b2
  | false => false
  end.

Definition orb (b1:bool) (b2:bool) : bool :=
  match b1 with
  | true => true
  | false => b2
  end.

(** The last two of these illustrate Coq's syntax for
    multi-argument function definitions.  The corresponding
    multi-argument application syntax is illustrated by the following
    "unit tests," which constitute a complete specification -- a truth
    table -- for the [orb] function: *)

Example test_orb1:  (orb true  false) = true.
Proof. simpl. reflexivity.  Qed.
Example test_orb2:  (orb false false) = false.
Proof. simpl. reflexivity.  Qed.
Example test_orb3:  (orb false true)  = true.
Proof. simpl. reflexivity.  Qed.
Example test_orb4:  (orb true  true)  = true.
Proof. simpl. reflexivity.  Qed.

(** We can also introduce some familiar syntax for the boolean
    operations we have just defined. The [Infix] command defines a new
    symbolic notation for an existing definition. *)

Infix "&&" := andb.
Infix "||" := orb.

Example test_orb5:  false || false || true = true.
Proof. simpl. reflexivity. Qed.

(** _A note on notation_: In [.v] files, we use square brackets
    to delimit fragments of Coq code within comments; this convention,
    also used by the [coqdoc] documentation tool, keeps them visually
    separate from the surrounding text.  In the html version of the
    files, these pieces of text appear in a [different font].

    The command [Admitted] can be used as a placeholder for an
    incomplete proof.  We'll use it in exercises, to indicate the
    parts that we're leaving for you -- i.e., your job is to replace
    [Admitted]s with real proofs. *)

(** **** Exercise: 1 star (nandb)  *)
(** Remove [admit] and complete the definition of the following
    function; then make sure that the [Example] assertions below can
    each be verified by Coq.  (Remove "[Admitted.]" and fill in each
    proof, following the model of the [orb] tests above.) The function
    should return [true] if either or both of its inputs are
    [false]. *)

Definition nandb (b1:bool) (b2:bool) : bool :=  negb(andb b1 b2).

Example test_nandb1:               (nandb true false) = true.
Proof. simpl. reflexivity.  Qed.
Example test_nandb2:               (nandb false false) = true.
Proof. simpl. reflexivity.  Qed.
Example test_nandb3:               (nandb false true) = true.
Proof. simpl. reflexivity.  Qed.
Example test_nandb4:               (nandb true true) = false.
Proof. simpl. reflexivity.  Qed.
(** [] *)

(** **** Exercise: 1 star (andb3)  *)
(** Do the same for the [andb3] function below. This function should
    return [true] when all of its inputs are [true], and [false]
    otherwise. *)

Definition andb3 (b1:bool) (b2:bool) (b3:bool) : bool := andb b1 (andb b2 b3).

Example test_andb31:                 (andb3 true true true) = true.
Proof. simpl. reflexivity.  Qed.
Example test_andb32:                 (andb3 false true true) = false.
Proof. simpl. reflexivity.  Qed.
Example test_andb33:                 (andb3 true false true) = false.
Proof. simpl. reflexivity.  Qed.
Example test_andb34:                 (andb3 true true false) = false.
Proof. simpl. reflexivity.  Qed.
(** [] *)

(* ================================================================= *)
(** ** Function Types *)

(** Every expression in Coq has a type, describing what sort of
    thing it computes. The [Check] command asks Coq to print the type
    of an expression. *)

Check true.
(* ===> true : bool *)
Check (negb true).
(* ===> negb true : bool *)

(** Functions like [negb] itself are also data values, just like
    [true] and [false].  Their types are called _function types_, and
    they are written with arrows. *)

Check negb.
(* ===> negb : bool -> bool *)

(** The type of [negb], written [bool -> bool] and pronounced
    "[bool] arrow [bool]," can be read, "Given an input of type
    [bool], this function produces an output of type [bool]."
    Similarly, the type of [andb], written [bool -> bool -> bool], can
    be read, "Given two inputs, both of type [bool], this function
    produces an output of type [bool]." *)

(* ================================================================= *)
(** ** Modules *)

(** Coq provides a _module system_, to aid in organizing large
    developments.  In this course we won't need most of its features,
    but one is useful: If we enclose a collection of declarations
    between [Module X] and [End X] markers, then, in the remainder of
    the file after the [End], these definitions are referred to by
    names like [X.foo] instead of just [foo].  We will use this
    feature to introduce the definition of the type [nat] in an inner
    module so that it does not interfere with the one from the
    standard library (which we want to use in the rest because it
    comes with a tiny bit of convenient special notation).  *)

Module NatPlayground.

(* ================================================================= *)
(** ** Numbers *)

(** The types we have defined so far are examples of "enumerated
    types": their definitions explicitly enumerate a finite set of
    elements.  A more interesting way of defining a type is to give a
    collection of _inductive rules_ describing its elements.  For
    example, we can define (a unary representation of) the natural
    numbers as follows: *)

Inductive nat : Type :=
  | O : nat
  | S : nat -> nat.

(** The clauses of this definition can be read:
      - [O] is a natural number (note that this is the letter "[O],"
        not the numeral "[0]").
      - [S] is a "constructor" that takes a natural number and yields
        another one -- that is, if [n] is a natural number, then [S n]
        is too. *)

(** Let's look at this in a little more detail.

    Every inductively defined set ([day], [nat], [bool], etc.) is
    actually a set of _expressions_ built from _constructors_
    like [O], [S], [true], [false], [monday], etc.  The definition of
    [nat] says how expressions in the set [nat] can be built:

    - [O] and [S] are constructors;
    - the expression [O] belongs to the set [nat];
    - if [n] is an expression belonging to the set [nat], then [S n]
      is also an expression belonging to the set [nat]; and
    - expressions formed in these two ways are the only ones belonging
      to the set [nat]. *)

(** The same rules apply for our definitions of [day] and
    [bool]. (The annotations we used for their constructors are
    analogous to the one for the [O] constructor, indicating that they
    don't take any arguments.)

    The above conditions are the precise force of the [Inductive]
    declaration.  They imply that the expression [O], the expression
    [S O], the expression [S (S O)], the expression [S (S (S O))], and
    so on all belong to the set [nat], while other expressions built
    from data constructors, like [true], [andb true false], [S (S
    false)], and [O (O (O S))] do not.

    A critical point here is that what we've done so far is just to
    define a _representation_ of numbers: a way of writing them down.
    The names [O] and [S] are arbitrary, and at this point they have
    no special meaning -- they are just two different marks that we
    can use to write down numbers (together with a rule that says any
    [nat] will be written as some string of [S] marks followed by an
    [O]).  If we like, we can write essentially the same definition
    this way: *)

Inductive nat' : Type :=
  | stop : nat'
  | tick : nat' -> nat'.

(** The _interpretation_ of these marks comes from how we use them to
    compute. *)

(** We can do this by writing functions that pattern match on
    representations of natural numbers just as we did above with
    booleans and days -- for example, here is the predecessor
    function: *)

Definition pred (n : nat) : nat :=
  match n with
    | O => O
    | S n' => n'
  end.

(** The second branch can be read: "if [n] has the form [S n']
    for some [n'], then return [n']."  *)

End NatPlayground.

Definition minustwo (n : nat) : nat :=
  match n with
    | O => O
    | S O => O
    | S (S n') => n'
  end.

(** Because natural numbers are such a pervasive form of data,
    Coq provides a tiny bit of built-in magic for parsing and printing
    them: ordinary arabic numerals can be used as an alternative to
    the "unary" notation defined by the constructors [S] and [O].  Coq
    prints numbers in arabic form by default: *)

Check (S (S (S (S O)))).
  (* ===> 4 : nat *)
Compute (minustwo 4).
  (* ===> 2 : nat *)

(** The constructor [S] has the type [nat -> nat], just like the
    functions [minustwo] and [pred]: *)

Check S.
Check pred.
Check minustwo.

(** These are all things that can be applied to a number to yield a
    number.  However, there is a fundamental difference between the
    first one and the other two: functions like [pred] and [minustwo]
    come with _computation rules_ -- e.g., the definition of [pred]
    says that [pred 2] can be simplified to [1] -- while the
    definition of [S] has no such behavior attached.  Although it is
    like a function in the sense that it can be applied to an
    argument, it does not _do_ anything at all!  It is just a way of
    writing down numbers.  (Think about standard arabic numerals: the
    numeral [1] is not a computation; it's a piece of data.  When we
    write [111] to mean the number one hundred and eleven, we are
    using [1], three times, to write down a concrete representation of
    a number.)

    For most function definitions over numbers, just pattern matching
    is not enough: we also need recursion.  For example, to check that
    a number [n] is even, we may need to recursively check whether
    [n-2] is even.  To write such functions, we use the keyword
    [Fixpoint]. *)

Fixpoint evenb (n:nat) : bool :=
  match n with
  | O        => true
  | S O      => false
  | S (S n') => evenb n'
  end.

(** We can define [oddb] by a similar [Fixpoint] declaration, but here
    is a simpler definition: *)

Definition oddb (n:nat) : bool   :=   negb (evenb n).

Example test_oddb1:    oddb 1 = true.
Proof. simpl. reflexivity.  Qed.
Example test_oddb2:    oddb 4 = false.
Proof. simpl. reflexivity.  Qed.

(** (You will notice if you step through these proofs that
    [simpl] actually has no effect on the goal -- all of the work is
    done by [reflexivity].  We'll see more about why that is shortly.)

    Naturally, we can also define multi-argument functions by
    recursion.  *)

Module NatPlayground2.

Fixpoint plus (n : nat) (m : nat) : nat :=
  match n with
    | O => m
    | S n' => S (plus n' m)
  end.

(** Adding three to two now gives us five, as we'd expect. *)

Compute (plus 3 2).

(** The simplification that Coq performs to reach this conclusion can
    be visualized as follows: *)

(*  [plus (S (S (S O))) (S (S O))]
==> [S (plus (S (S O)) (S (S O)))]
      by the second clause of the [match]
==> [S (S (plus (S O) (S (S O))))]
      by the second clause of the [match]
==> [S (S (S (plus O (S (S O)))))]
      by the second clause of the [match]
==> [S (S (S (S (S O))))]
      by the first clause of the [match]
*)

(** As a notational convenience, if two or more arguments have
    the same type, they can be written together.  In the following
    definition, [(n m : nat)] means just the same as if we had written
    [(n : nat) (m : nat)]. *)

Fixpoint mult (n m : nat) : nat :=
  match n with
    | O => O
    | S n' => plus m (mult n' m)
  end.

Example test_mult1: (mult 3 3) = 9.
Proof. simpl. reflexivity.  Qed.

(** You can match two expressions at once by putting a comma
    between them: *)

Fixpoint minus (n m:nat) : nat :=
  match n, m with
  | O   , _    => O
  | S _ , O    => n
  | S n', S m' => minus n' m'
  end.

(** The _ in the first line is a _wildcard pattern_.  Writing _ in a
    pattern is the same as writing some variable that doesn't get used
    on the right-hand side.  This avoids the need to invent a variable
    name. *)

End NatPlayground2.

Fixpoint exp (base power : nat) : nat :=
  match power with
    | O => S O
    | S p => mult base (exp base p)
  end.

(** **** Exercise: 1 star (factorial)  *)
(** Recall the standard mathematical factorial function:

       factorial(0)  =  1
       factorial(n)  =  n * factorial(n-1)     (if n>0)

    Translate this into Coq. *)

Fixpoint factorial (n:nat) : nat :=
  match n with
    | O => S(O)
    | S n' => mult n (factorial n')
  end
.

Example test_factorial1:          (factorial 3) = 6.
Proof. simpl. reflexivity. Qed.
Example test_factorial2:          (factorial 5) = (mult 10 12).
Proof. simpl. reflexivity. Qed.
(** [] *)

(** We can make numerical expressions a little easier to read and
    write by introducing _notations_ for addition, multiplication, and
    subtraction. *)

Notation "x + y" := (plus x y)
                       (at level 50, left associativity)
                       : nat_scope.
Notation "x - y" := (minus x y)
                       (at level 50, left associativity)
                       : nat_scope.
Notation "x * y" := (mult x y)
                       (at level 40, left associativity)
                       : nat_scope.

Check ((0 + 1) + 1).

(** (The [level], [associativity], and [nat_scope] annotations
    control how these notations are treated by Coq's parser.  The
    details are not important for our purposes, but interested readers
    can refer to the optional "More on Notation" section at the end of
    this chapter.)

    Note that these do not change the definitions we've already made:
    they are simply instructions to the Coq parser to accept [x + y]
    in place of [plus x y] and, conversely, to the Coq pretty-printer
    to display [plus x y] as [x + y]. *)

(** When we say that Coq comes with nothing built-in, we really mean
    it: even equality testing for numbers is a user-defined operation!
    We now define a function [beq_nat], which tests [nat]ural numbers
    for [eq]uality, yielding a [b]oolean.  Note the use of nested
    [match]es (we could also have used a simultaneous match, as we did
    in [minus].) *)

Fixpoint beq_nat (n m : nat) : bool :=
  match n with
  | O => match m with
         | O => true
         | S m' => false
         end
  | S n' => match m with
            | O => false
            | S m' => beq_nat n' m'
            end
  end.

(** The [leb] function tests whether its first argument is less than or
  equal to its second argument, yielding a boolean. *)

Fixpoint leb (n m : nat) : bool :=
  match n with
  | O => true
  | S n' =>
      match m with
      | O => false
      | S m' => leb n' m'
      end
  end.

Example test_leb1:             (leb 2 2) = true.
Proof. simpl. reflexivity.  Qed.
Example test_leb2:             (leb 2 4) = true.
Proof. simpl. reflexivity.  Qed.
Example test_leb3:             (leb 4 2) = false.
Proof. simpl. reflexivity.  Qed.

(** **** Exercise: 1 star (blt_nat)  *)
(** The [blt_nat] function tests [nat]ural numbers for [l]ess-[t]han,
    yielding a [b]oolean.  Instead of making up a new [Fixpoint] for
    this one, define it in terms of a previously defined function. *)

Definition blt_nat (n m : nat) : bool :=

  andb (leb n m) (negb (beq_nat n m))

.

Example test_blt_nat1:             (blt_nat 2 2) = false.
Proof. simpl. reflexivity.  Qed.
Example test_blt_nat2:             (blt_nat 2 4) = true.
Proof. simpl. reflexivity.  Qed.
Example test_blt_nat3:             (blt_nat 4 2) = false.
Proof. simpl. reflexivity.  Qed.
(** [] *)

(* ################################################################# *)
(** * Proof by Simplification *)

(** Now that we've defined a few datatypes and functions, let's
    turn to stating and proving properties of their behavior.
    Actually, we've already started doing this: each [Example] in the
    previous sections makes a precise claim about the behavior of some
    function on some particular inputs.  The proofs of these claims
    were always the same: use [simpl] to simplify both sides of the
    equation, then use [reflexivity] to check that both sides contain
    identical values.

    The same sort of "proof by simplification" can be used to prove
    more interesting properties as well.  For example, the fact that
    [0] is a "neutral element" for [+] on the left can be proved just
    by observing that [0 + n] reduces to [n] no matter what [n] is, a
    fact that can be read directly off the definition of [plus].*)

Theorem plus_O_n : forall n : nat, 0 + n = n.
Proof.
  intros n. simpl. reflexivity.  Qed.

(** (You may notice that the above statement looks different in
    the [.v] file in your IDE than it does in the HTML rendition in
    your browser, if you are viewing both. In [.v] files, we write the
    [forall] universal quantifier using the reserved identifier
    "forall."  When the [.v] files are converted to HTML, this gets
    transformed into an upside-down-A symbol.)

    This is a good place to mention that [reflexivity] is a bit
    more powerful than we have admitted. In the examples we have seen,
    the calls to [simpl] were actually not needed, because
    [reflexivity] can perform some simplification automatically when
    checking that two sides are equal; [simpl] was just added so that
    we could see the intermediate state -- after simplification but
    before finishing the proof.  Here is a shorter proof of the
    theorem: *)

Theorem plus_O_n' : forall n : nat, 0 + n = n.
Proof.
  intros n. reflexivity. Qed.

(** Moreover, it will be useful later to know that [reflexivity]
    does somewhat _more_ simplification than [simpl] does -- for
    example, it tries "unfolding" defined terms, replacing them with
    their right-hand sides.  The reason for this difference is that,
    if reflexivity succeeds, the whole goal is finished and we don't
    need to look at whatever expanded expressions [reflexivity] has
    created by all this simplification and unfolding; by contrast,
    [simpl] is used in situations where we may have to read and
    understand the new goal that it creates, so we would not want it
    blindly expanding definitions and leaving the goal in a messy
    state.

    The form of the theorem we just stated and its proof are almost
    exactly the same as the simpler examples we saw earlier; there are
    just a few differences.

    First, we've used the keyword [Theorem] instead of [Example].
    This difference is purely a matter of style; the keywords
    [Example] and [Theorem] (and a few others, including [Lemma],
    [Fact], and [Remark]) mean exactly the same thing to Coq.

    Second, we've added the quantifier [forall n:nat], so that our
    theorem talks about _all_ natural numbers [n].  In order to prove
    theorems of this form, we need to to be able to reason by
    _assuming_ the existence of an arbitrary natural number [n].  This
    is achieved in the proof by [intros n], which moves the quantifier
    from the goal to a _context_ of current assumptions. In effect, we
    start the proof by saying "Suppose [n] is some arbitrary
    number..."

    The keywords [intros], [simpl], and [reflexivity] are examples of
    _tactics_.  A tactic is a command that is used between [Proof] and
    [Qed] to guide the process of checking some claim we are making.
    We will see several more tactics in the rest of this chapter and
    yet more in future chapters.

    Other similar theorems can be proved with the same pattern. *)

Theorem plus_1_l : forall n:nat, 1 + n = S n.
Proof.
  intros n. reflexivity.  Qed.

Theorem mult_0_l : forall n:nat, 0 * n = 0.
Proof.
  intros n. reflexivity.  Qed.

(** The [_l] suffix in the names of these theorems is
    pronounced "on the left." *)

(** It is worth stepping through these proofs to observe how the
    context and the goal change.  You may want to add calls to [simpl]
    before [reflexivity] to see the simplifications that Coq performs
    on the terms before checking that they are equal.

    Although simplification is powerful enough to prove some fairly
    general facts, there are many statements that cannot be handled by
    simplification alone.  For instance, we cannot use it to prove
    that [0] is also a neutral element for [+] _on the right_. *)

Theorem plus_n_O : forall n, n = n + 0.
Proof.
  intros n. simpl. (* Doesn't do anything! *)
(** (Can you explain why this happens?  Step through both proofs
    with Coq and notice how the goal and context change.)

    When stuck in the middle of a proof, we can use the [Abort]
    command to give up on it for the moment. *)
Abort.

(** The next chapter will introduce _induction_, a powerful
    technique that can be used for proving this goal.  For the moment,
    though, let's look at a few more simple tactics. *)

(* ################################################################# *)
(** * Proof by Rewriting *)

(** This theorem is a bit more interesting than the others we've
    seen: *)

Theorem plus_id_example : forall n m:nat,
  n = m ->
  n + n = m + m.

(** Instead of making a universal claim about all numbers [n] and [m],
    it talks about a more specialized property that only holds when [n
    = m].  The arrow symbol is pronounced "implies."

    As before, we need to be able to reason by assuming the existence
    of some numbers [n] and [m].  We also need to assume the hypothesis
    [n = m]. The [intros] tactic will serve to move all three of these
    from the goal into assumptions in the current context.

    Since [n] and [m] are arbitrary numbers, we can't just use
    simplification to prove this theorem.  Instead, we prove it by
    observing that, if we are assuming [n = m], then we can replace
    [n] with [m] in the goal statement and obtain an equality with the
    same expression on both sides.  The tactic that tells Coq to
    perform this replacement is called [rewrite]. *)

Proof.
  (* move both quantifiers into the context: *)
  intros n m.
  (* move the hypothesis into the context: *)
  intros H.
  (* rewrite the goal using the hypothesis: *)
  rewrite -> H.
  reflexivity.  Qed.

(** The first line of the proof moves the universally quantified
    variables [n] and [m] into the context.  The second moves the
    hypothesis [n = m] into the context and gives it the name [H].
    The third tells Coq to rewrite the current goal ([n + n = m + m])
    by replacing the left side of the equality hypothesis [H] with the
    right side.

    (The arrow symbol in the [rewrite] has nothing to do with
    implication: it tells Coq to apply the rewrite from left to right.
    To rewrite from right to left, you can use [rewrite <-].  Try
    making this change in the above proof and see what difference it
    makes.) *)

(** **** Exercise: 1 star (plus_id_exercise)  *)
(** Remove "[Admitted.]" and fill in the proof. *)

Theorem plus_id_exercise : forall n m o : nat,
  n = m -> m = o -> n + m = m + o.
Proof.
  intros n m o. intros H. intros H'.
  rewrite -> H. rewrite <- H'. reflexivity.
Qed.
(** [] *)

(** The [Admitted] command tells Coq that we want to skip trying
    to prove this theorem and just accept it as a given.  This can be
    useful for developing longer proofs, since we can state subsidiary
    lemmas that we believe will be useful for making some larger
    argument, use [Admitted] to accept them on faith for the moment,
    and continue working on the main argument until we are sure it
    makes sense; then we can go back and fill in the proofs we
    skipped.  Be careful, though: every time you say [Admitted] you
    are leaving a door open for total nonsense to enter Coq's nice,
    rigorous, formally checked world! *)

(** We can also use the [rewrite] tactic with a previously proved
    theorem instead of a hypothesis from the context. If the statement
    of the previously proved theorem involves quantified variables,
    as in the example below, Coq tries to instantiate them
    by matching with the current goal. *)

Theorem mult_0_plus : forall n m : nat,
  (0 + n) * m = n * m.
Proof.
  intros n m.
  rewrite -> plus_O_n.
  reflexivity.  Qed.

(** **** Exercise: 2 stars (mult_S_1)  *)
Theorem mult_S_1 : forall n m : nat,
  m = S n ->
  m * (1 + n) = m * m.
Proof.
  intros n m. intros H.
  simpl. rewrite <- H. reflexivity.
Qed.

(* (N.b. This proof can actually be completed without using [rewrite],
   but please do use [rewrite] for the sake of the exercise.) *)
(** [] *)

(* ################################################################# *)
(** * Proof by Case Analysis *)

(** Of course, not everything can be proved by simple
    calculation and rewriting: In general, unknown, hypothetical
    values (arbitrary numbers, booleans, lists, etc.) can block
    simplification.  For example, if we try to prove the following
    fact using the [simpl] tactic as above, we get stuck. *)

Theorem plus_1_neq_0_firsttry : forall n : nat,
  beq_nat (n + 1) 0 = false.
Proof.
  intros n.
  simpl.  (* does nothing! *)
Abort.

(** The reason for this is that the definitions of both
    [beq_nat] and [+] begin by performing a [match] on their first
    argument.  But here, the first argument to [+] is the unknown
    number [n] and the argument to [beq_nat] is the compound
    expression [n + 1]; neither can be simplified.

    To make progress, we need to consider the possible forms of [n]
    separately.  If [n] is [O], then we can calculate the final result
    of [beq_nat (n + 1) 0] and check that it is, indeed, [false].  And
    if [n = S n'] for some [n'], then, although we don't know exactly
    what number [n + 1] yields, we can calculate that, at least, it
    will begin with one [S], and this is enough to calculate that,
    again, [beq_nat (n + 1) 0] will yield [false].

    The tactic that tells Coq to consider, separately, the cases where
    [n = O] and where [n = S n'] is called [destruct]. *)

Theorem plus_1_neq_0 : forall n : nat,
  beq_nat (n + 1) 0 = false.
Proof.
  intros n. destruct n as [| n'].
  - reflexivity.
  - reflexivity.   Qed.

(** The [destruct] generates _two_ subgoals, which we must then
    prove, separately, in order to get Coq to accept the theorem. The
    annotation "[as [| n']]" is called an _intro pattern_.  It tells
    Coq what variable names to introduce in each subgoal.  In general,
    what goes between the square brackets is a _list of lists_ of
    names, separated by [|].  In this case, the first component is
    empty, since the [O] constructor is nullary (it doesn't have any
    arguments).  The second component gives a single name, [n'], since
    [S] is a unary constructor.

    The [-] signs on the second and third lines are called _bullets_,
    and they mark the parts of the proof that correspond to each
    generated subgoal.  The proof script that comes after a bullet is
    the entire proof for a subgoal.  In this example, each of the
    subgoals is easily proved by a single use of [reflexivity], which
    itself performs some simplification -- e.g., the first one
    simplifies [beq_nat (S n' + 1) 0] to [false] by first rewriting
    [(S n' + 1)] to [S (n' + 1)], then unfolding [beq_nat], and then
    simplifying the [match].

    Marking cases with bullets is entirely optional: if bullets are
    not present, Coq simply asks you to prove each subgoal in
    sequence, one at a time. But it is a good idea to use bullets.
    For one thing, they make the structure of a proof apparent, making
    it more readable. Also, bullets instruct Coq to ensure that a
    subgoal is complete before trying to verify the next one,
    preventing proofs for different subgoals from getting mixed
    up. These issues become especially important in large
    developments, where fragile proofs lead to long debugging
    sessions.

    There are no hard and fast rules for how proofs should be
    formatted in Coq -- in particular, where lines should be broken
    and how sections of the proof should be indented to indicate their
    nested structure.  However, if the places where multiple subgoals
    are generated are marked with explicit bullets at the beginning of
    lines, then the proof will be readable almost no matter what
    choices are made about other aspects of layout.

    This is also a good place to mention one other piece of somewhat
    obvious advice about line lengths.  Beginning Coq users sometimes
    tend to the extremes, either writing each tactic on its own line
    or writing entire proofs on one line.  Good style lies somewhere
    in the middle.  One reasonable convention is to limit yourself to
    80-character lines.

    The [destruct] tactic can be used with any inductively defined
    datatype.  For example, we use it next to prove that boolean
    negation is involutive -- i.e., that negation is its own
    inverse. *)

Theorem negb_involutive : forall b : bool,
  negb (negb b) = b.
Proof.
  intros b. destruct b.
  - reflexivity.
  - reflexivity.  Qed.

(** Note that the [destruct] here has no [as] clause because
    none of the subcases of the [destruct] need to bind any variables,
    so there is no need to specify any names.  (We could also have
    written [as [|]], or [as []].)  In fact, we can omit the [as]
    clause from _any_ [destruct] and Coq will fill in variable names
    automatically.  This is generally considered bad style, since Coq
    often makes confusing choices of names when left to its own
    devices.

    It is sometimes useful to invoke [destruct] inside a subgoal,
    generating yet more proof obligations. In this case, we use
    different kinds of bullets to mark goals on different "levels."
    For example: *)

Theorem andb_commutative : forall b c, andb b c = andb c b.
Proof.
  intros b c. destruct b.
  - destruct c.
    + reflexivity.
    + reflexivity.
  - destruct c.
    + reflexivity.
    + reflexivity.
Qed.

(** Each pair of calls to [reflexivity] corresponds to the
    subgoals that were generated after the execution of the [destruct c]
    line right above it. *)

(** Besides [-] and [+], we can use [*] (asterisk) as a third kind of
    bullet.  We can also enclose sub-proofs in curly braces, which is
    useful in case we ever encounter a proof that generates more than
    three levels of subgoals: *)

Theorem andb_commutative' : forall b c, andb b c = andb c b.
Proof.
  intros b c. destruct b.
  { destruct c.
    { reflexivity. }
    { reflexivity. } }
  { destruct c.
    { reflexivity. }
    { reflexivity. } }
Qed.

(** Since curly braces mark both the beginning and the end of a
    proof, they can be used for multiple subgoal levels, as this
    example shows. Furthermore, curly braces allow us to reuse the
    same bullet shapes at multiple levels in a proof: *)

Theorem andb3_exchange :
  forall b c d, andb (andb b c) d = andb (andb b d) c.
Proof.
  intros b c d. destruct b.
  - destruct c.
    { destruct d.
      - reflexivity.
      - reflexivity. }
    { destruct d.
      - reflexivity.
      - reflexivity. }
  - destruct c.
    { destruct d.
      - reflexivity.
      - reflexivity. }
    { destruct d.
      - reflexivity.
      - reflexivity. }
Qed.

(** Before closing the chapter, let's mention one final
    convenience.  As you may have noticed, many proofs perform case
    analysis on a variable right after introducing it:

       intros x y. destruct y as [|y].

    This pattern is so common that Coq provides a shorthand for it: we
    can perform case analysis on a variable when introducing it by
    using an intro pattern instead of a variable name. For instance,
    here is a shorter proof of the [plus_1_neq_0] theorem above. *)

Theorem plus_1_neq_0' : forall n : nat,
  beq_nat (n + 1) 0 = false.
Proof.
  intros [|n].
  - reflexivity.
  - reflexivity.  Qed.

(** If there are no arguments to name, we can just write [[]]. *)

Theorem andb_commutative'' :
  forall b c, andb b c = andb c b.
Proof.
  intros [] [].
  - reflexivity.
  - reflexivity.
  - reflexivity.
  - reflexivity.
Qed.

(** **** Exercise: 2 stars (andb_true_elim2)  *)
(** Prove the following claim, marking cases (and subcases) with
    bullets when you use [destruct]. *)

Theorem andb_true_elim2 : forall b c : bool,
  andb b c = true -> c = true.
Proof.
  intros b c. destruct b.
  - destruct c.
    + reflexivity.
    + simpl. intros H. rewrite -> H. reflexivity.
  - destruct c.
    + simpl. intros H. reflexivity.
    + simpl. intros H. rewrite -> H. reflexivity.
Qed.
(** [] *)

(** **** Exercise: 1 star (zero_nbeq_plus_1)  *)
Theorem zero_nbeq_plus_1 : forall n : nat,
  beq_nat 0 (n + 1) = false.
Proof.
  intros n. destruct n.
  - simpl. reflexivity.
  - simpl. reflexivity.
Qed.
(** [] *)

(* ================================================================= *)
(** ** More on Notation (Optional) *)

(** (In general, sections marked Optional are not needed to follow the
    rest of the book, except possibly other Optional sections.  On a
    first reading, you might want to skim these sections so that you
    know what's there for future reference.)

    Recall the notation definitions for infix plus and times: *)

Notation "x + y" := (plus x y)
                       (at level 50, left associativity)
                       : nat_scope.
Notation "x * y" := (mult x y)
                       (at level 40, left associativity)
                       : nat_scope.

(** For each notation symbol in Coq, we can specify its _precedence
    level_ and its _associativity_.  The precedence level [n] is
    specified by writing [at level n]; this helps Coq parse compound
    expressions.  The associativity setting helps to disambiguate
    expressions containing multiple occurrences of the same
    symbol. For example, the parameters specified above for [+] and
    [*] say that the expression [1+2*3*4] is shorthand for
    [(1+((2*3)*4))]. Coq uses precedence levels from 0 to 100, and
    _left_, _right_, or _no_ associativity.  We will see more examples
    of this later, e.g., in the [Lists]
    chapter.

    Each notation symbol is also associated with a _notation scope_.
    Coq tries to guess what scope is meant from context, so when it
    sees [S(O*O)] it guesses [nat_scope], but when it sees the
    cartesian product (tuple) type [bool*bool] (which we'll see in
    later chapters) it guesses [type_scope].  Occasionally, it is
    necessary to help it out with percent-notation by writing
    [(x*y)%nat], and sometimes in what Coq prints it will use [%nat]
    to indicate what scope a notation is in.

    Notation scopes also apply to numeral notation ([3], [4], [5],
    etc.), so you may sometimes see [0%nat], which means [O] (the
    natural number [0] that we're using in this chapter), or [0%Z],
    which means the Integer zero (which comes from a different part of
    the standard library).

    Pro tip: Coq's notation mechanism is not especially powerful.
    Don't expect too much from it! *)

(* ================================================================= *)
(** ** Fixpoints and Structural Recursion (Optional) *)

(** Here is a copy of the definition of addition: *)

Fixpoint plus' (n : nat) (m : nat) : nat :=
  match n with
  | O => m
  | S n' => S (plus' n' m)
  end.

(** When Coq checks this definition, it notes that [plus'] is
    "decreasing on 1st argument."  What this means is that we are
    performing a _structural recursion_ over the argument [n] -- i.e.,
    that we make recursive calls only on strictly smaller values of
    [n].  This implies that all calls to [plus'] will eventually
    terminate.  Coq demands that some argument of _every_ [Fixpoint]
    definition is "decreasing."

    This requirement is a fundamental feature of Coq's design: In
    particular, it guarantees that every function that can be defined
    in Coq will terminate on all inputs.  However, because Coq's
    "decreasing analysis" is not very sophisticated, it is sometimes
    necessary to write functions in slightly unnatural ways. *)

(** **** Exercise: 2 stars, optional (decreasing)  *)
(** To get a concrete sense of this, find a way to write a sensible
    [Fixpoint] definition (of a simple function on numbers, say) that
    _does_ terminate on all inputs, but that Coq will reject because
    of this restriction. *)

(* FILL IN HERE *)

(** [] *)

(* ################################################################# *)
(** * More Exercises *)

(** **** Exercise: 2 stars (boolean_functions)  *)
(** Use the tactics you have learned so far to prove the following
    theorem about boolean functions. *)

Theorem identity_fn_applied_twice :
  forall (f : bool -> bool),
  (forall (x : bool), f x = x) ->
  forall (b : bool), f (f b) = b.
Proof.
  intros f x b. rewrite <- x. rewrite <- x. reflexivity.
 Qed.

(** Now state and prove a theorem [negation_fn_applied_twice] similar
    to the previous one but where the second hypothesis says that the
    function [f] has the property that [f x = negb x].*)

Theorem negation_fn_applied_twice :
  forall (f : bool -> bool),
  (forall (x : bool), f x = negb x) ->
  forall (b : bool), f (f b) = b.
Proof.
  intros f x b. rewrite -> x. rewrite -> x. rewrite -> negb_involutive. reflexivity.
 Qed.
(** [] *)

(** **** Exercise: 2 stars (andb_eq_orb)  *)
(** Prove the following theorem.  (You may want to first prove a
    subsidiary lemma or two. Alternatively, remember that you do
    not have to introduce all hypotheses at the same time.) *)

Theorem andb_eq_orb :
  forall (b c : bool),
  (andb b c = orb b c) ->
  b = c.
Proof.
  intros b c. destruct b.
  - simpl. intros H. rewrite -> H. reflexivity.
  - simpl. intros H. rewrite <- H. reflexivity.
Qed.
(** [] *)

(** **** Exercise: 3 stars (binary)  *)
(** Consider a different, more efficient representation of natural
    numbers using a binary rather than unary system.  That is, instead
    of saying that each natural number is either zero or the successor
    of a natural number, we can say that each binary number is either

      - zero,
      - twice a binary number, or
      - one more than twice a binary number.

    (a) First, write an inductive definition of the type [bin]
        corresponding to this description of binary numbers.

    (Hint: Recall that the definition of [nat] above,

         Inductive nat : Type := | O : nat | S : nat -> nat.

    says nothing about what [O] and [S] "mean."  It just says "[O] is
    in the set called [nat], and if [n] is in the set then so is [S
    n]."  The interpretation of [O] as zero and [S] as successor/plus
    one comes from the way that we _use_ [nat] values, by writing
    functions to do things with them, proving things about them, and
    so on.  Your definition of [bin] should be correspondingly simple;
    it is the functions you will write next that will give it
    mathematical meaning.)

    (b) Next, write an increment function [incr] for binary numbers,
        and a function [bin_to_nat] to convert binary numbers to unary
        numbers.

    (c) Write five unit tests [test_bin_incr1], [test_bin_incr2], etc.
        for your increment and binary-to-unary functions.  (A "unit
        test" in Coq is a specific [Example] that can be proved with
        just [reflexivity], as we've done for several of our
        definitions.)  Notice that incrementing a binary number and
        then converting it to unary should yield the same result as
        first converting it to unary and then incrementing. *)

Inductive bin : Type :=
  | zero : bin
  | Z : bin -> bin
  | l : bin -> bin.

Fixpoint incr (n : bin) : bin :=
  match n with
    | zero => l zero
    | Z n' => l n'
    | l n' => Z (incr n')
  end.

Fixpoint convert (b : bin) : nat :=
  match b with
    | zero => 0
    | Z b' => 2 * convert (b')
    | l b' => (2 * convert (b')) + 1
  end.

Example test_bin_incr1: convert (incr(zero)) = 1.
Proof. simpl. reflexivity. Qed.

Example test_bin_incr2: convert (incr (incr(zero))) = 2.
Proof. simpl. reflexivity. Qed.

Example test_bin_zero: convert zero = 0.
Proof. simpl. reflexivity. Qed.

Example test_bin_1: convert (l (zero)) = 1.
Proof. simpl. reflexivity. Qed.
(* 8 = 1000 *)
Example test_bin_8: convert (Z (Z (Z (l (zero))))) = 8.
Proof. simpl. reflexivity. Qed.
(* 8 = 0000 1000 *)
Example test_bin_08: convert (Z (Z (Z (l (Z (Z (Z (Z (zero))))))))) = 8.
Proof. simpl. reflexivity. Qed.
(* 7 = 0000 0111 *)
Example test_bin_7: convert (  (l (l (l (zero))))) = 7.
Proof. simpl. reflexivity. Qed.
(* 23 = 0001 0111 *)
Example test_bin_23: convert (l ( l (l (Z (l (zero)))))) = 23.
Proof. simpl. reflexivity. Qed.

(** [] *)

(** $Date: 2016-09-01 14:03:18 +0200 (Jeu, 01 sep 2016) $ *)


Require Import Init.

(*

直観主義命題論理と古典命題論理の任意の式が常に正しいか判定できる。
それを実装したプログラムがある。ある人がパースの公理と排中律の関係を知りたくてこのような式を与えた。

(P \/ ~ P) -> (((P -> Q) -> P) -> P)

結果は「正しい」となった。次に逆であるこの式を与えた。

(((P -> Q) -> P) -> P) -> (P \/ ~ P)

すると結果は「誤っている」となった。なぜか？

*)

Goal (forall p q : Prop, ((p -> q) -> p) -> p) -> (forall a : Prop, a \/ ~ a).
Proof.
 intros peirce a.
 apply peirce with False.
 intros H.
 right.
 intros A.
 apply H.
 left.
 apply A.
Defined peirce_to_excluded_middle.

Goal (forall a : Prop, a \/ ~ a) -> (forall p q : Prop, ((p -> q) -> p) -> p).
Proof.
 intros exmi p q H.
 destruct (exmi p) as [P | Pn].
 -
  apply P.
 -
  apply H.
  intros P.
  exfalso.
  apply Pn.
  apply P.
Defined excluded_middle_to_peirce.

(*

誤りは上のように全称量化が必要なこと。最初の時はなぜ正しかったのか？

excluded_middle_to_peirceの証明を見ると引数exmiにpを渡している。
exmi p : p \/ ~ pとなり、一般のexmiがなくてもこれだけあればよいことになる。
こうして置き換えたものはちょうど最初に与えた式に一致する。

*)

(*

Thank

https://github.com/suharahiromichi/coq/blob/2aedd465c255a6aac1466258041d4930211460d9/coq_classical.v

.

*)


(* LISTA DE EXERCÍCIOS 1
   =====================================
   ALUNOS:
      PAULO RENATO LANZARIN - 228818
      MARCOS HENRIQUE BACKES - 228483
      MATHEUS ROSA CASTANHEIRA - 228400
   =====================================
*)

(* Bibliotecas importadas *)

Require Import Arith.

(* Definição indutiva dos termos de L0 *)

Inductive term :=
 | zero   : term
 | succ   : term -> term
 | true   : term
 | false  : term
 | iszero : term -> term
 | pred   : term -> term
 | ifte   : term -> term -> term -> term
.

(* Definição indutiva da propriedade de ser um número *)

Inductive nv : term -> Prop :=
 | zeroNum : nv zero
 | succNum : forall n, (nv n) -> (nv (succ n))
.

(* Definição indutiva de valor : números OU booleanos *)

Inductive value : term -> Prop :=
 | trueVal  : value true
 | falseVal : value false
 | numVal   : forall n, (nv n) -> (value n)
.

(* Testando termos *)
Check ifte false zero (succ zero).

(* Testando valores do tipo termo *)
Check value (iszero true).

(* Provando uma propriedade *)
Theorem teste1 : value (succ zero).
Proof.
constructor 3.
constructor 2.
constructor 1.
Qed.

(* Provando uma propriedade 2 *)
Theorem teste2 : value (succ zero).
Proof.
apply numVal.
apply succNum.
apply zeroNum.
Qed.

(* Provando uma propriedade negada *)
Lemma teste : ~ value (iszero true).
Proof.
unfold not.
intro H.
inversion H.
subst.
inversion H0.
Qed.

(*****************************************************************)

(* Definição da semântica operacional *)
Inductive step : term -> term -> Prop :=
 | e_iftrue     : forall t2 t3,        step (ifte true  t2 t3) t2
 | e_iffalse    : forall t2 t3,        step (ifte false t2 t3) t3
 | e_if         : forall t1 t2 t3 t1', (step t1 t1') -> step (ifte t1 t2 t3) (ifte t1' t2 t3)
 | e_succ       : forall t t',         step t t' -> step (succ t) (succ t')
 | e_predzero   :                      step (pred zero) zero
 | e_predsucc   : forall t,  (nv t) -> step (pred (succ t)) t
 | e_pred       : forall t t',         step t t' -> step (pred t) (pred t')
 | e_iszerozero :                      step (iszero zero) true
 | e_iszerosucc : forall t,  (nv t) -> step (iszero (succ t)) false
 | e_iszero     : forall t t',         step t t' -> step (iszero t) (iszero t')
.

(* Definição de forma normal *)

Definition NF (t:term) : Prop := forall t', not (step t t').

(*****************************************************************)

(* Exercício : TODO NV É FORMA NORMAL *)
Theorem nvNF : forall (t:term), nv t -> NF t.
Proof.
induction t.
intro. unfold NF. intro. unfold not. intro. inversion H0. (* zero *)
intro. inversion H. subst. apply IHt in H1. unfold NF in H1.  intro. unfold not. intro. inversion H0. subst. unfold not in H1. apply (H1 t'0) in H3. assumption. (* succ *)
intro. unfold NF. intro. intro. inversion H0. (* true *)
intro. unfold NF. intro. intro. inversion H0. (* false *)
intro. inversion H. (* iszero *)
intro. inversion H. (* pred *)
intro. inversion H. (* ifte *)
Qed.

(* Exercício : TODO VALOR É FORMA NORMAL *)

Theorem valueNF : forall (t:term), value t -> NF t.
Proof.
intro.
intro.
induction H.
  (* H=true *)
  unfold NF.
  intro.
  unfold not.
  intro.
  inversion H.
  (* H=false *)
  unfold NF.
  intro.
  unfold not.
  intro.
  inversion H.
  (* H=nv *)
  apply nvNF.
  assumption.
Qed.

(* DETERMINISMO *)

Theorem determinismo : forall t t' t'', (step t t') -> (step t t'') -> (t' = t'').
Proof.
induction t.
(* zero *)
intros. inversion H.
(* succ *)
intros.  inversion H. inversion H0. subst. assert (t'0 = t'1). apply (IHt t'0 t'1 H2 H5). apply f_equal. assumption.
(* true *)
intros. inversion H.
(* false *)
intros. inversion H.
(* iszero *)

intros. inversion H. subst. inversion H0. reflexivity. inversion H2.
inversion H0.  subst. discriminate H5. reflexivity. subst.
apply succNum in H2. apply nvNF in H2. unfold NF in H2. unfold not in H2. apply H2 in H5. exfalso. assumption.
inversion H0.  subst.  inversion H2. subst. apply succNum in H5. apply nvNF in H5. unfold NF in H5. unfold not in H5. exfalso. apply (H5 t'0 H2). subst. apply f_equal. apply (IHt t'0 t'1 H2 H5).

intros. inversion H. subst. inversion H0. reflexivity. inversion H2.
inversion H0.  subst. discriminate H5. subst. injection H4. intro. symmetry.  assumption.
subst.
apply succNum in H2. apply nvNF in H2. unfold NF in H2. unfold not in H2. apply H2 in H5. exfalso. assumption.
inversion H0.  subst.  inversion H2. subst. apply succNum in H5. apply nvNF in H5. unfold NF in H5. unfold not in H5. exfalso. apply (H5 t'0 H2). subst. apply f_equal. apply (IHt t'0 t'1 H2 H5).

intros.
inversion H. subst. inversion H0. subst. reflexivity. inversion H5.

inversion H0. subst. discriminate. subst. assumption. subst. inversion H9. subst. inversion H0. subst. inversion H5. subst. inversion H5. subst. assert (t1'=t1'0). apply IHt1. assumption. assumption. rewrite H1. reflexivity.

Qed.

(* QUESTÃO 1A *)
Inductive type :=
 | tBool : type
 | tNat  : type
.
(* QUESTÃO 1B *)
Inductive hasType : term -> type -> Prop :=
 | t_true   :                                         hasType true       tBool
 | t_false  :                                         hasType false      tBool
 | t_zero   :                                         hasType zero       tNat
 | t_succ   : forall t,           hasType t tNat   -> hasType (succ t)   tNat
 | t_pred   : forall t,           hasType t tNat   -> hasType (pred t)   tNat
 | t_iszero : forall t,           hasType t tNat   -> hasType (iszero t) tBool
 | t_ifte   : forall t1 t2 t3 ty, hasType t1 tBool ->
                                  hasType t2 ty    ->
                                  hasType t3 ty    -> hasType (ifte t1 t2 t3) ty
.

(* QUESTÃO 2A *)
Theorem dois_a : hasType (ifte (iszero (succ (succ zero))) (succ zero) zero) tNat.
Proof.
apply t_ifte.
apply t_iszero.
apply t_succ.
apply t_succ.
apply t_zero.
apply t_succ.
apply t_zero.
apply t_zero.
Qed.

(* QUESTÃO 2B *)
Theorem dois_b : step (ifte (iszero (succ (succ zero))) (succ zero) zero)
                       (ifte false (succ zero) zero).
Proof.
apply e_if.
apply e_iszerosucc.
apply succNum.
apply zeroNum.
Qed.

(* QUESTÃO 2C *)
Theorem dois_c : ~ (step (ifte (iszero (succ (succ zero))) (succ zero) zero) zero).
Proof.
unfold not.
intro.
inversion H.
Qed.

(* QUESTÃO 2D *)
Theorem dois_d : ~ forall t : term, value t.
Proof.
unfold not.
intro.
assert (value (iszero zero)).
apply (H (iszero zero)).
inversion H0.
inversion H1.
Qed.

(* QUESTÃO 2E *)
Theorem dois_e : forall t : term, (value t) \/ ~(value t).
Proof.
intros.
unfold not.
induction t.
  (* zero *)
  left. apply numVal. apply zeroNum.
  (* succ t *)
  inversion IHt.
  inversion H.
  (* value t*)
    (* succ true *)
    subst. right. intro. inversion H0. subst. inversion H1. subst. inversion H3.
    (* succ false *)
    subst. right. intro. inversion H0. subst. inversion H1. subst. inversion H3.
    (* succ nv *)
    subst. left. apply numVal. apply succNum. assumption.
  (* value t -> False *)
  right. intro. apply H. apply numVal. inversion H0. subst. inversion H1. subst. assumption.
  (* true *)
  left. apply trueVal.
  (* false *)
  left. apply falseVal.
  (* iszero t *)
  right. intro. inversion H. inversion H0.
  (* pred t *)
  right. intro. inversion H. inversion H0.
  (* ifte t1 t2 t3 *)
  right. intro. inversion H. inversion H0.
Qed.

(* QUESTÃO 3A *)
Theorem unicidade_de_tipos : forall t, forall T1 T2 : type, (hasType t T1) -> (hasType t T2) -> T1 = T2.
Proof.
intros.
induction H.
  (* true *)
  inversion H0.
  reflexivity.
  (* false *)
  inversion H0.
  reflexivity.
  (* zero *)
  inversion H0.
  reflexivity.
  (* succ t *)
  inversion H0.
  reflexivity.
  (* pred t *)
  inversion H0.
  reflexivity.
  (* iszero t *)
  inversion H0.
  reflexivity.
  (* ifte t1 t2 t3 *)
  inversion H0.
  subst.
  apply IHhasType2.
  assumption.
Qed.


(** * ProofObjects: The Curry-Howard Correspondence *)

Set Warnings "-notation-overridden,-parsing".
From LF Require Export IndProp.

(** "_Algorithms are the computational content of proofs_."  --Robert Harper *)

(** We have seen that Coq has mechanisms both for _programming_,
		using inductive data types like [nat] or [list] and functions over
		these types, and for _proving_ properties of these programs, using
		inductive propositions (like [even]), implication, universal
		quantification, and the like.  So far, we have mostly treated
		these mechanisms as if they were quite separate, and for many
		purposes this is a good way to think.  But we have also seen hints
		that Coq's programming and proving facilities are closely related.
		For example, the keyword [Inductive] is used to declare both data
		types and propositions, and [->] is used both to describe the type
		of functions on data and logical implication.  This is not just a
		syntactic accident!  In fact, programs and proofs in Coq are
		almost the same thing.  In this chapter we will study how this
		works.

		We have already seen the fundamental idea: provability in Coq is
		represented by concrete _evidence_.  When we construct the proof
		of a basic proposition, we are actually building a tree of
		evidence, which can be thought of as a data structure.

		If the proposition is an implication like [A -> B], then its proof
		will be an evidence _transformer_: a recipe for converting
		evidence for A into evidence for B.  So at a fundamental level,
		proofs are simply programs that manipulate evidence. *)

(** Question: If evidence is data, what are propositions themselves?

		Answer: They are types! *)

(** Look again at the formal definition of the [even] property.  *)

Print even.
(* ==>
	Inductive even : nat -> Prop :=
		| ev_0 : even 0
		| ev_SS : forall n, even n -> even (S (S n)).
*)

(** Suppose we introduce an alternative pronunciation of "[:]".
		Instead of "has type," we can say "is a proof of."  For example,
		the second line in the definition of [even] declares that [ev_0 : even
		0].  Instead of "[ev_0] has type [even 0]," we can say that "[ev_0]
		is a proof of [even 0]." *)

(** This pun between types and propositions -- between [:] as "has type"
		and [:] as "is a proof of" or "is evidence for" -- is called the
		_Curry-Howard correspondence_.  It proposes a deep connection
		between the world of logic and the world of computation:

								 propositions  ~  types
								 proofs        ~  data values

		See [Wadler 2015] (in Bib.v) for a brief history and up-to-date exposition. *)

(** Many useful insights follow from this connection.  To begin with,
		it gives us a natural interpretation of the type of the [ev_SS]
		constructor: *)

Check ev_SS.
(* ===> ev_SS : forall n,
									even n ->
									even (S (S n)) *)

(** This can be read "[ev_SS] is a constructor that takes two
		arguments -- a number [n] and evidence for the proposition [even
		n] -- and yields evidence for the proposition [even (S (S n))]." *)

(** Now let's look again at a previous proof involving [even]. *)

Theorem ev_4 : even 4.
Proof.
	apply ev_SS. apply ev_SS. apply ev_0. Qed.

(** As with ordinary data values and functions, we can use the [Print]
		command to see the _proof object_ that results from this proof
		script. *)

Print ev_4.
(* ===> ev_4 = ev_SS 2 (ev_SS 0 ev_0)
		 : even 4  *)

(** Indeed, we can also write down this proof object _directly_,
		without the need for a separate proof script: *)

Check (ev_SS 2 (ev_SS 0 ev_0)).
(* ===> even 4 *)

(** The expression [ev_SS 2 (ev_SS 0 ev_0)] can be thought of as
		instantiating the parameterized constructor [ev_SS] with the
		specific arguments [2] and [0] plus the corresponding proof
		objects for its premises [even 2] and [even 0].  Alternatively, we can
		think of [ev_SS] as a primitive "evidence constructor" that, when
		applied to a particular number, wants to be further applied to
		evidence that that number is even; its type,

			forall n, even n -> even (S (S n)),

		expresses this functionality, in the same way that the polymorphic
		type [forall X, list X] expresses the fact that the constructor
		[nil] can be thought of as a function from types to empty lists
		with elements of that type. *)

(** We saw in the [Logic] chapter that we can use function
		application syntax to instantiate universally quantified variables
		in lemmas, as well as to supply evidence for assumptions that
		these lemmas impose.  For instance: *)

Theorem ev_4': even 4.
Proof.
	apply (ev_SS 2 (ev_SS 0 ev_0)).
Qed.

(* ################################################################# *)
(** * Proof Scripts *)

(** The _proof objects_ we've been discussing lie at the core of how
		Coq operates.  When Coq is following a proof script, what is
		happening internally is that it is gradually constructing a proof
		object -- a term whose type is the proposition being proved.  The
		tactics between [Proof] and [Qed] tell it how to build up a term
		of the required type.  To see this process in action, let's use
		the [Show Proof] command to display the current state of the proof
		tree at various points in the following tactic proof. *)

Theorem ev_4'' : even 4.
Proof.
	Show Proof.
	apply ev_SS.
	Show Proof.
	apply ev_SS.
	Show Proof.
	apply ev_0.
	Show Proof.
Qed.

(** At any given moment, Coq has constructed a term with a
		"hole" (indicated by [?Goal] here, and so on), and it knows what
		type of evidence is needed to fill this hole.

		Each hole corresponds to a subgoal, and the proof is
		finished when there are no more subgoals.  At this point, the
		evidence we've built stored in the global context under the name
		given in the [Theorem] command. *)

(** Tactic proofs are useful and convenient, but they are not
		essential: in principle, we can always construct the required
		evidence by hand, as shown above. Then we can use [Definition]
		(rather than [Theorem]) to give a global name directly to this
		evidence. *)

Definition ev_4''' : even 4 :=
	ev_SS 2 (ev_SS 0 ev_0).

(** All these different ways of building the proof lead to exactly the
		same evidence being saved in the global environment. *)

Print ev_4.
(* ===> ev_4    =   ev_SS 2 (ev_SS 0 ev_0) : even 4 *)
Print ev_4'.
(* ===> ev_4'   =   ev_SS 2 (ev_SS 0 ev_0) : even 4 *)
Print ev_4''.
(* ===> ev_4''  =   ev_SS 2 (ev_SS 0 ev_0) : even 4 *)
Print ev_4'''.
(* ===> ev_4''' =   ev_SS 2 (ev_SS 0 ev_0) : even 4 *)

(** **** Exercise: 2 stars, standard (eight_is_even)

		Give a tactic proof and a proof object showing that [even 8]. *)

Theorem ev_8 : even 8.
Proof.
	apply ev_SS. apply ev_SS. apply ev_SS. apply ev_SS. apply ev_0.
Qed.

Definition ev_8' : even 8 :=
	ev_SS 6 (ev_SS 4 (ev_SS 2 (ev_SS 0 ev_0))).
(** [] *)

(* ################################################################# *)
(** * Quantifiers, Implications, Functions *)

(** In Coq's computational universe (where data structures and
		programs live), there are two sorts of values with arrows in their
		types: _constructors_ introduced by [Inductive]ly defined data
		types, and _functions_.

		Similarly, in Coq's logical universe (where we carry out proofs),
		there are two ways of giving evidence for an implication:
		constructors introduced by [Inductive]ly defined propositions,
		and... functions! *)

(** For example, consider this statement: *)

Theorem ev_plus4 : forall n, even n -> even (4 + n).
Proof.
	intros n H. simpl.
	apply ev_SS.
	apply ev_SS.
	apply H.
Qed.

(** What is the proof object corresponding to [ev_plus4]?

		We're looking for an expression whose _type_ is [forall n, even n ->
		even (4 + n)] -- that is, a _function_ that takes two arguments (one
		number and a piece of evidence) and returns a piece of evidence!

		Here it is: *)

Definition ev_plus4' : forall n, even n -> even (4 + n) :=
	fun (n : nat) => fun (H : even n) =>
		ev_SS (S (S n)) (ev_SS n H).

(** Recall that [fun n => blah] means "the function that, given [n],
		yields [blah]," and that Coq treats [4 + n] and [S (S (S (S n)))]
		as synonyms. Another equivalent way to write this definition is: *)

Definition ev_plus4'' (n : nat) (H : even n) : even (4 + n) :=
	ev_SS (S (S n)) (ev_SS n H).

Check ev_plus4''.
(* ===>
		 : forall n : nat, even n -> even (4 + n) *)

(** When we view the proposition being proved by [ev_plus4] as a
		function type, one interesting point becomes apparent: The second
		argument's type, [even n], mentions the _value_ of the first
		argument, [n].

		While such _dependent types_ are not found in conventional
		programming languages, they can be useful in programming too, as
		the recent flurry of activity in the functional programming
		community demonstrates. *)

(** Notice that both implication ([->]) and quantification ([forall])
		correspond to functions on evidence.  In fact, they are really the
		same thing: [->] is just a shorthand for a degenerate use of
		[forall] where there is no dependency, i.e., no need to give a
		name to the type on the left-hand side of the arrow:

					 forall (x:nat), nat
				=  forall (_:nat), nat
				=  nat -> nat
*)

(** For example, consider this proposition: *)

Definition ev_plus2 : Prop :=
	forall n, forall (E : even n), even (n + 2).

(** A proof term inhabiting this proposition would be a function
		with two arguments: a number [n] and some evidence [E] that [n] is
		even.  But the name [E] for this evidence is not used in the rest
		of the statement of [ev_plus2], so it's a bit silly to bother
		making up a name for it.  We could write it like this instead,
		using the dummy identifier [_] in place of a real name: *)

Definition ev_plus2' : Prop :=
	forall n, forall (_ : even n), even (n + 2).

(** Or, equivalently, we can write it in more familiar notation: *)

Definition ev_plus2'' : Prop :=
	forall n, even n -> even (n + 2).

(** In general, "[P -> Q]" is just syntactic sugar for
		"[forall (_:P), Q]". *)

(* ################################################################# *)
(** * Programming with Tactics *)

(** If we can build proofs by giving explicit terms rather than
		executing tactic scripts, you may be wondering whether we can
		build _programs_ using _tactics_ rather than explicit terms.
		Naturally, the answer is yes! *)

Definition add1 : nat -> nat.
intro n.
Show Proof.
apply S.
Show Proof.
apply n. Defined.

Print add1.
(* ==>
		add1 = fun n : nat => S n
				 : nat -> nat
*)

Compute add1 2.
(* ==> 3 : nat *)

(** Notice that we terminate the [Definition] with a [.] rather than
		with [:=] followed by a term.  This tells Coq to enter _proof
		scripting mode_ to build an object of type [nat -> nat].  Also, we
		terminate the proof with [Defined] rather than [Qed]; this makes
		the definition _transparent_ so that it can be used in computation
		like a normally-defined function.  ([Qed]-defined objects are
		opaque during computation.)

		This feature is mainly useful for writing functions with dependent
		types, which we won't explore much further in this book.  But it
		does illustrate the uniformity and orthogonality of the basic
		ideas in Coq. *)

(* ################################################################# *)
(** * Logical Connectives as Inductive Types *)

(** Inductive definitions are powerful enough to express most of the
		connectives we have seen so far.  Indeed, only universal
		quantification (with implication as a special case) is built into
		Coq; all the others are defined inductively.  We'll see these
		definitions in this section. *)

Module Props.

(* ================================================================= *)
(** ** Conjunction *)

(** To prove that [P /\ Q] holds, we must present evidence for both
		[P] and [Q].  Thus, it makes sense to define a proof object for [P
		/\ Q] as consisting of a pair of two proofs: one for [P] and
		another one for [Q]. This leads to the following definition. *)

Module And.

Inductive and (P Q : Prop) : Prop :=
| conj : P -> Q -> and P Q.

End And.

(** Notice the similarity with the definition of the [prod] type,
		given in chapter [Poly]; the only difference is that [prod] takes
		[Type] arguments, whereas [and] takes [Prop] arguments. *)

Print prod.
(* ===>
	 Inductive prod (X Y : Type) : Type :=
	 | pair : X -> Y -> X * Y. *)

(** This similarity should clarify why [destruct] and [intros]
		patterns can be used on a conjunctive hypothesis.  Case analysis
		allows us to consider all possible ways in which [P /\ Q] was
		proved -- here just one (the [conj] constructor).

		Similarly, the [split] tactic actually works for any inductively
		defined proposition with exactly one constructor.  In particular,
		it works for [and]: *)

Lemma and_comm : forall P Q : Prop, P /\ Q <-> Q /\ P.
Proof.
	intros P Q. split.
	- intros [HP HQ]. split.
		+ apply HQ.
		+ apply HP.
	- intros [HP HQ]. split.
		+ apply HQ.
		+ apply HP.
Qed.

(** This shows why the inductive definition of [and] can be
		manipulated by tactics as we've been doing.  We can also use it to
		build proofs directly, using pattern-matching.  For instance: *)

Definition and_comm'_aux P Q (H : P /\ Q) : Q /\ P :=
	match H with
	| conj HP HQ => conj HQ HP
	end.

Definition and_comm' P Q : P /\ Q <-> Q /\ P :=
	conj (and_comm'_aux P Q) (and_comm'_aux Q P).

(** **** Exercise: 2 stars, standard, optional (conj_fact)

		Construct a proof object demonstrating the following proposition. *)

Definition conj_fact : forall P Q R, P /\ Q -> Q /\ R -> P /\ R :=
	fun (P Q R: Prop) (HPQ: P /\ Q) (HPR: Q /\ R) =>
	match HPQ, HPR with
	| conj HP _, conj _ HR => conj HP HR
	end.
(** [] *)

(* ================================================================= *)
(** ** Disjunction *)

(** The inductive definition of disjunction uses two constructors, one
		for each side of the disjunct: *)

Module Or.

Inductive or (P Q : Prop) : Prop :=
| or_introl : P -> or P Q
| or_intror : Q -> or P Q.

End Or.

(** This declaration explains the behavior of the [destruct] tactic on
		a disjunctive hypothesis, since the generated subgoals match the
		shape of the [or_introl] and [or_intror] constructors.

		Once again, we can also directly write proof objects for theorems
		involving [or], without resorting to tactics. *)

(** **** Exercise: 2 stars, standard, optional (or_commut'')

		Try to write down an explicit proof object for [or_commut] (without
		using [Print] to peek at the ones we already defined!). *)

Definition or_comm : forall P Q, P \/ Q -> Q \/ P :=
	fun (P Q : Prop) (H: P \/ Q) =>
	match H with
	| or_introl HP => or_intror Q HP
	| or_intror HQ => or_introl P HQ
	end.
(** [] *)

(* ================================================================= *)
(** ** Existential Quantification *)

(** To give evidence for an existential quantifier, we package a
		witness [x] together with a proof that [x] satisfies the property
		[P]: *)

Module Ex.

Inductive ex {A : Type} (P : A -> Prop) : Prop :=
| ex_intro : forall x : A, P x -> ex P.

End Ex.

(** This may benefit from a little unpacking.  The core definition is
		for a type former [ex] that can be used to build propositions of
		the form [ex P], where [P] itself is a _function_ from witness
		values in the type [A] to propositions.  The [ex_intro]
		constructor then offers a way of constructing evidence for [ex P],
		given a witness [x] and a proof of [P x]. *)

(** The more familiar form [exists x, P x] desugars to an expression
		involving [ex]: *)

Check ex (fun n => even n).
(* ===> exists n : nat, even n
				: Prop *)

(** Here's how to define an explicit proof object involving [ex]: *)

Definition some_nat_is_even : exists n, even n :=
	ex_intro even 4 (ev_SS 2 (ev_SS 0 ev_0)).

(** **** Exercise: 2 stars, standard, optional (ex_ev_Sn)

		Complete the definition of the following proof object: *)

Definition ex_ev_Sn : ex (fun n => even (S n)) :=
	ex_intro (fun n => even (S n)) 1 (ev_SS 0 ev_0).
(** [] *)

(* ================================================================= *)
(** ** [True] and [False] *)

(** The inductive definition of the [True] proposition is simple: *)

Inductive True : Prop :=
	| I : True.

(** It has one constructor (so every proof of [True] is the same, so
		being given a proof of [True] is not informative.) *)

(** [False] is equally simple -- indeed, so simple it may look
		syntactically wrong at first glance! *)

Inductive False : Prop := .

(** That is, [False] is an inductive type with _no_ constructors --
		i.e., no way to build evidence for it. *)

End Props.

(* ################################################################# *)
(** * Equality *)

(** Even Coq's equality relation is not built in.  It has the
		following inductive definition.  (Actually, the definition in the
		standard library is a slight variant of this, which gives an
		induction principle that is slightly easier to use.) *)

Module MyEquality.

Inductive eq {X:Type} : X -> X -> Prop :=
| eq_refl : forall x, eq x x.

Notation "x == y" := (eq x y)
										(at level 70, no associativity)
										: type_scope.

(** The way to think about this definition is that, given a set [X],
		it defines a _family_ of propositions "[x] is equal to [y],"
		indexed by pairs of values ([x] and [y]) from [X].  There is just
		one way of constructing evidence for members of this family:
		applying the constructor [eq_refl] to a type [X] and a single
		value [x : X], which yields evidence that [x] is equal to [x].

		Other types of the form [eq x y] where [x] and [y] are not the
		same are thus uninhabited. *)

(** We can use [eq_refl] to construct evidence that, for example, [2 =
		2].  Can we also use it to construct evidence that [1 + 1 = 2]?
		Yes, we can.  Indeed, it is the very same piece of evidence!

		The reason is that Coq treats as "the same" any two terms that are
		_convertible_ according to a simple set of computation rules.

		These rules, which are similar to those used by [Compute], include
		evaluation of function application, inlining of definitions, and
		simplification of [match]es.  *)

Lemma four: 2 + 2 == 1 + 3.
Proof.
	apply eq_refl.
Qed.

(** The [reflexivity] tactic that we have used to prove equalities up
		to now is essentially just shorthand for [apply eq_refl].

		In tactic-based proofs of equality, the conversion rules are
		normally hidden in uses of [simpl] (either explicit or implicit in
		other tactics such as [reflexivity]).

		But you can see them directly at work in the following explicit
		proof objects: *)

Definition four' : 2 + 2 == 1 + 3 :=
	eq_refl 4.

Definition singleton : forall (X:Type) (x:X), []++[x] == x::[]  :=
	fun (X:Type) (x:X) => eq_refl [x].

(** **** Exercise: 2 stars, standard (equality__leibniz_equality)

		The inductive definition of equality implies _Leibniz equality_:
		what we mean when we say "[x] and [y] are equal" is that every
		property on [P] that is true of [x] is also true of [y].  *)

Lemma equality__leibniz_equality : forall (X : Type) (x y: X),
	x == y -> forall P:X->Prop, P x -> P y.
Proof.
	intros. destruct H. assumption.
Qed.
(** [] *)

(** **** Exercise: 5 stars, standard, optional (leibniz_equality__equality)

		Show that, in fact, the inductive definition of equality is
		_equivalent_ to Leibniz equality: *)

Lemma leibniz_equality__equality : forall (X : Type) (x y: X),
	(forall P:X->Prop, P x -> P y) -> x == y.
Proof.
	intros X x y H. apply H. apply eq_refl.
Qed.

(** [] *)

End MyEquality.

(* ================================================================= *)
(** ** Inversion, Again *)

(** We've seen [inversion] used with both equality hypotheses and
		hypotheses about inductively defined propositions.  Now that we've
		seen that these are actually the same thing, we're in a position
		to take a closer look at how [inversion] behaves.

		In general, the [inversion] tactic...

		- takes a hypothesis [H] whose type [P] is inductively defined,
			and

		- for each constructor [C] in [P]'s definition,

			- generates a new subgoal in which we assume [H] was
				built with [C],

			- adds the arguments (premises) of [C] to the context of
				the subgoal as extra hypotheses,

			- matches the conclusion (result type) of [C] against the
				current goal and calculates a set of equalities that must
				hold in order for [C] to be applicable,

			- adds these equalities to the context (and, for convenience,
				rewrites them in the goal), and

			- if the equalities are not satisfiable (e.g., they involve
				things like [S n = O]), immediately solves the subgoal. *)

(** _Example_: If we invert a hypothesis built with [or], there are
		two constructors, so two subgoals get generated.  The
		conclusion (result type) of the constructor ([P \/ Q]) doesn't
		place any restrictions on the form of [P] or [Q], so we don't get
		any extra equalities in the context of the subgoal. *)

(** _Example_: If we invert a hypothesis built with [and], there is
		only one constructor, so only one subgoal gets generated.  Again,
		the conclusion (result type) of the constructor ([P /\ Q]) doesn't
		place any restrictions on the form of [P] or [Q], so we don't get
		any extra equalities in the context of the subgoal.  The
		constructor does have two arguments, though, and these can be seen
		in the context in the subgoal. *)

(** _Example_: If we invert a hypothesis built with [eq], there is
		again only one constructor, so only one subgoal gets generated.
		Now, though, the form of the [eq_refl] constructor does give us
		some extra information: it tells us that the two arguments to [eq]
		must be the same!  The [inversion] tactic adds this fact to the
		context. *)

(* Wed Jan 9 12:02:45 EST 2019 *)


(** * Rel: Properties of Relations *)

(** This short (and optional) chapter develops some basic definitions
    and a few theorems about binary relations in Coq.  The key
    definitions are repeated where they are actually used (in the
    [Smallstep] chapter of _Programming Language Foundations_),
    so readers who are already comfortable with these ideas can safely
    skim or skip this chapter.  However, relations are also a good
    source of exercises for developing facility with Coq's basic
    reasoning facilities, so it may be useful to look at this material
    just after the [IndProp] chapter. *)

Set Warnings "-notation-overridden,-parsing,-deprecated-hint-without-locality".
From LF Require Export IndProp.

(* ################################################################# *)
(** * Relations *)

(** A binary _relation_ on a set [X] is a family of propositions
    parameterized by two elements of [X] -- i.e., a proposition about
    pairs of elements of [X].  *)

Definition relation (X: Type) := X -> X -> Prop.

(** Somewhat confusingly, the Coq standard library hijacks the generic
    term "relation" for this specific instance of the idea. To
    maintain consistency with the library, we will do the same.  So,
    henceforth, the Coq identifier [relation] will always refer to a
    binary relation _on_ some set (between the set and itself),
    whereas in ordinary mathematical English the word "relation" can
    refer either to this specific concept or the more general concept
    of a relation between any number of possibly different sets.  The
    context of the discussion should always make clear which is
    meant. *)

(** An example relation on [nat] is [le], the less-than-or-equal-to
    relation, which we usually write [n1 <= n2]. *)

Print le.
(* ====> Inductive le (n : nat) : nat -> Prop :=
             le_n : n <= n
           | le_S : forall m : nat, n <= m -> n <= S m *)
Check le : nat -> nat -> Prop.
Check le : relation nat.
(** (Why did we write it this way instead of starting with [Inductive
    le : relation nat...]?  Because we wanted to put the first [nat]
    to the left of the [:], which makes Coq generate a somewhat nicer
    induction principle for reasoning about [<=].) *)

(* ################################################################# *)
(** * Basic Properties *)

(** As anyone knows who has taken an undergraduate discrete math
    course, there is a lot to be said about relations in general,
    including ways of classifying relations (as reflexive, transitive,
    etc.), theorems that can be proved generically about certain sorts
    of relations, constructions that build one relation from another,
    etc.  For example... *)

(* ----------------------------------------------------------------- *)
(** *** Partial Functions *)

(** A relation [R] on a set [X] is a _partial function_ if, for every
    [x], there is at most one [y] such that [R x y] -- i.e., [R x y1]
    and [R x y2] together imply [y1 = y2]. *)

Definition partial_function {X: Type} (R: relation X) :=
  forall x y1 y2 : X, R x y1 -> R x y2 -> y1 = y2.

(** For example, the [next_nat] relation is a partial function. *)
Inductive next_nat : nat -> nat -> Prop :=
  | nn n : next_nat n (S n).

Check next_nat : relation nat.

Theorem next_nat_partial_function :
  partial_function next_nat.
Proof.
  unfold partial_function.
  intros x y1 y2 H1 H2.
  inversion H1. inversion H2.
  reflexivity.  Qed.

(** However, the [<=] relation on numbers is not a partial
    function.  (Assume, for a contradiction, that [<=] is a partial
    function.  But then, since [0 <= 0] and [0 <= 1], it follows that
    [0 = 1].  This is nonsense, so our assumption was
    contradictory.) *)

Theorem le_not_a_partial_function :
  ~ (partial_function le).
Proof.
  unfold not. unfold partial_function. intros Hc.
  assert (0 = 1) as Nonsense. {
    apply Hc with (x := 0).
    - apply le_n.
    - apply le_S. apply le_n. }
  discriminate Nonsense.   Qed.

(** **** Exercise: 2 stars, standard, optional (total_relation_not_partial_function)

    Show that the [total_relation] defined in (an exercise in)
    [IndProp] is not a partial function. *)

(** Copy the definition of [total_relation] from your [IndProp]
    here so that this file can be graded on its own.  *)
Inductive total_relation : nat -> nat -> Prop :=
  | total_rel (n m : nat) : total_relation n m
.

Theorem total_relation_not_partial_function :
  ~ (partial_function total_relation).
Proof.
  unfold not. unfold partial_function. intros Hc.
  assert (0 = 1) as Nonsense. {
    apply (Hc 1 0 1). apply total_rel. apply total_rel.
  }
  discriminate Nonsense.
Qed.
(** [] *)

(** **** Exercise: 2 stars, standard, optional (empty_relation_partial_function)

    Show that the [empty_relation] defined in (an exercise in)
    [IndProp] is a partial function. *)

(** Copy the definition of [empty_relation] from your [IndProp]
    here so that this file can be graded on its own.  *)
Inductive empty_relation : nat -> nat -> Prop :=
.

Theorem empty_relation_partial_function :
  partial_function empty_relation.
Proof.
  intros x y1 y2 rel. inversion rel.
Qed.
(** [] *)

(* ----------------------------------------------------------------- *)
(** *** Reflexive Relations *)

(** A _reflexive_ relation on a set [X] is one for which every element
    of [X] is related to itself. *)

Definition reflexive {X: Type} (R: relation X) :=
  forall a : X, R a a.

Theorem le_reflexive :
  reflexive le.
Proof.
  unfold reflexive. intros n. apply le_n.  Qed.

(* ----------------------------------------------------------------- *)
(** *** Transitive Relations *)

(** A relation [R] is _transitive_ if [R a c] holds whenever [R a b]
    and [R b c] do. *)

Definition transitive {X: Type} (R: relation X) :=
  forall a b c : X, (R a b) -> (R b c) -> (R a c).

Theorem le_trans :
  transitive le.
Proof.
  intros n m o Hnm Hmo.
  induction Hmo.
  - (* le_n *) apply Hnm.
  - (* le_S *) apply le_S. apply IHHmo.  Qed.

Theorem lt_trans:
  transitive lt.
Proof.
  unfold lt. unfold transitive.
  intros n m o Hnm Hmo.
  apply le_S in Hnm.
  apply le_trans with (a := (S n)) (b := (S m)) (c := o).
  apply Hnm.
  apply Hmo. Qed.

(** **** Exercise: 2 stars, standard, optional (le_trans_hard_way)

    We can also prove [lt_trans] more laboriously by induction,
    without using [le_trans].  Do this. *)

Theorem lt_trans' :
  transitive lt.
Proof.
  (* Prove this by induction on evidence that [m] is less than [o]. *)
  unfold lt. unfold transitive.
  intros n m o Hnm Hmo.
  induction Hmo as [| m' Hm'o].
  - apply le_S in Hnm. apply Hnm.
  - apply le_S in IHHm'o. apply IHHm'o.
Qed.
(** [] *)

(** **** Exercise: 2 stars, standard, optional (lt_trans'')

    Prove the same thing again by induction on [o]. *)

Theorem lt_trans'' :
  transitive lt.
Proof.
  unfold lt. unfold transitive.
  intros n m o Hnm Hmo.
  induction o as [| o'].
  - inversion Hmo.
  - apply le_trans with (S m). apply le_S. apply Hnm. apply Hmo.
Qed.
(** [] *)

(** The transitivity of [le], in turn, can be used to prove some facts
    that will be useful later (e.g., for the proof of antisymmetry
    below)... *)

Theorem le_Sn_le : forall n m, S n <= m -> n <= m.
Proof.
  intros n m H. apply le_trans with (S n).
  - apply le_S. apply le_n.
  - apply H.
Qed.

(** **** Exercise: 1 star, standard, optional (le_S_n) *)
Theorem le_S_n : forall n m,
  (S n <= S m) -> (n <= m).
Proof.
  intros n m H.
  inversion H as [H1|m' H1 H'].
  - apply le_n.
  - apply le_Sn_le. apply H1.
Qed.
(** [] *)

(** **** Exercise: 2 stars, standard, optional (le_Sn_n_inf)

    Provide an informal proof of the following theorem:

    Theorem: For every [n], [~ (S n <= n)]

    A formal proof of this is an optional exercise below, but try
    writing an informal proof without doing the formal proof first.

    Proof: *)
    (* FILL IN HERE

    [] *)

(** **** Exercise: 1 star, standard, optional (le_Sn_n) *)
Theorem le_Sn_n : forall n,
  ~ (S n <= n).
Proof.
  intros n contra.
  induction n. inversion contra. apply le_S_n in contra. apply (IHn contra).
Qed.
(** [] *)

(** Reflexivity and transitivity are the main concepts we'll need for
    later chapters, but, for a bit of additional practice working with
    relations in Coq, let's look at a few other common ones... *)

(* ----------------------------------------------------------------- *)
(** *** Symmetric and Antisymmetric Relations *)

(** A relation [R] is _symmetric_ if [R a b] implies [R b a]. *)

Definition symmetric {X: Type} (R: relation X) :=
  forall a b : X, (R a b) -> (R b a).

(** **** Exercise: 2 stars, standard, optional (le_not_symmetric) *)
Theorem le_not_symmetric :
  ~ (symmetric le).
Proof.
  unfold not. unfold symmetric. intros contra.
  assert (Nonsense: 1 <= 0). {
    apply (contra 0 1). apply le_Sn_le. apply le_n.
  }
  inversion Nonsense.
Qed.
(** [] *)

(** A relation [R] is _antisymmetric_ if [R a b] and [R b a] together
    imply [a = b] -- that is, if the only "cycles" in [R] are trivial
    ones. *)

Definition antisymmetric {X: Type} (R: relation X) :=
  forall a b : X, (R a b) -> (R b a) -> a = b.

(** **** Exercise: 2 stars, standard, optional (le_antisymmetric) *)
Theorem le_antisymmetric :
  antisymmetric le.
Proof.
  unfold antisymmetric. intros a b H1 H2.
  inversion H1.
  - reflexivity.
  - exfalso.
    rewrite <- H0 in H2.
    assert (Nonsense: S m <= m). {
      apply le_trans with a.
      apply H2.
      apply H.
    }
    apply (le_Sn_n m Nonsense).
Qed.
(** [] *)

(** **** Exercise: 2 stars, standard, optional (le_step) *)
Theorem le_step : forall n m p,
  n < m ->
  m <= S p ->
  n <= p.
Proof.
  intros n m p H1 H2.
  assert (H3: S n <= S p). apply le_trans with m. apply H1. apply H2.
  apply (le_S_n n p H3).
Qed.
(** [] *)

(* ----------------------------------------------------------------- *)
(** *** Equivalence Relations *)

(** A relation is an _equivalence_ if it's reflexive, symmetric, and
    transitive.  *)

Definition equivalence {X:Type} (R: relation X) :=
  (reflexive R) /\ (symmetric R) /\ (transitive R).

(* ----------------------------------------------------------------- *)
(** *** Partial Orders and Preorders *)

(** A relation is a _partial order_ when it's reflexive,
    _anti_-symmetric, and transitive.  In the Coq standard library
    it's called just "order" for short. *)

Definition order {X:Type} (R: relation X) :=
  (reflexive R) /\ (antisymmetric R) /\ (transitive R).

(** A preorder is almost like a partial order, but doesn't have to be
    antisymmetric. *)

Definition preorder {X:Type} (R: relation X) :=
  (reflexive R) /\ (transitive R).

Theorem le_order :
  order le.
Proof.
  unfold order. split.
    - (* refl *) apply le_reflexive.
    - split.
      + (* antisym *) apply le_antisymmetric.
      + (* transitive. *) apply le_trans.  Qed.

(* ################################################################# *)
(** * Reflexive, Transitive Closure *)

(** The _reflexive, transitive closure_ of a relation [R] is the
    smallest relation that contains [R] and that is both reflexive and
    transitive.  Formally, it is defined like this in the Relations
    module of the Coq standard library: *)

Inductive clos_refl_trans {A: Type} (R: relation A) : relation A :=
  | rt_step x y (H : R x y) : clos_refl_trans R x y
  | rt_refl x : clos_refl_trans R x x
  | rt_trans x y z
        (Hxy : clos_refl_trans R x y)
        (Hyz : clos_refl_trans R y z) :
        clos_refl_trans R x z.

(** For example, the reflexive and transitive closure of the
    [next_nat] relation coincides with the [le] relation. *)

Theorem next_nat_closure_is_le : forall n m,
  (n <= m) <-> ((clos_refl_trans next_nat) n m).
Proof.
  intros n m. split.
  - (* -> *)
    intro H. induction H.
    + (* le_n *) apply rt_refl.
    + (* le_S *)
      apply rt_trans with m. apply IHle. apply rt_step.
      apply nn.
  - (* <- *)
    intro H. induction H.
    + (* rt_step *) inversion H. apply le_S. apply le_n.
    + (* rt_refl *) apply le_n.
    + (* rt_trans *)
      apply le_trans with y.
      apply IHclos_refl_trans1.
      apply IHclos_refl_trans2. Qed.

(** The above definition of reflexive, transitive closure is natural:
    it says, explicitly, that the reflexive and transitive closure of
    [R] is the least relation that includes [R] and that is closed
    under rules of reflexivity and transitivity.  But it turns out
    that this definition is not very convenient for doing proofs,
    since the "nondeterminism" of the [rt_trans] rule can sometimes
    lead to tricky inductions.  Here is a more useful definition: *)

Inductive clos_refl_trans_1n {A : Type}
                             (R : relation A) (x : A)
                             : A -> Prop :=
  | rt1n_refl : clos_refl_trans_1n R x x
  | rt1n_trans (y z : A)
      (Hxy : R x y) (Hrest : clos_refl_trans_1n R y z) :
      clos_refl_trans_1n R x z.

(** Our new definition of reflexive, transitive closure "bundles"
    the [rt_step] and [rt_trans] rules into the single rule step.
    The left-hand premise of this step is a single use of [R],
    leading to a much simpler induction principle.

    Before we go on, we should check that the two definitions do
    indeed define the same relation...

    First, we prove two lemmas showing that [clos_refl_trans_1n] mimics
    the behavior of the two "missing" [clos_refl_trans]
    constructors.  *)

Lemma rsc_R : forall (X:Type) (R:relation X) (x y : X),
  R x y -> clos_refl_trans_1n R x y.
Proof.
  intros X R x y H.
  apply rt1n_trans with y. apply H. apply rt1n_refl.   Qed.

(** **** Exercise: 2 stars, standard, optional (rsc_trans) *)
Lemma rsc_trans :
  forall (X:Type) (R: relation X) (x y z : X),
      clos_refl_trans_1n R x y  ->
      clos_refl_trans_1n R y z ->
      clos_refl_trans_1n R x z.
Proof.
  intros X R x y z H1 H2.
  induction H1 as [y | x y y' Hxy _ IH].
  - apply H2.
  - apply rt1n_trans with y. apply Hxy. apply (IH H2).
Qed.
(** [] *)

(** Then we use these facts to prove that the two definitions of
    reflexive, transitive closure do indeed define the same
    relation. *)

(** **** Exercise: 3 stars, standard, optional (rtc_rsc_coincide) *)
Theorem rtc_rsc_coincide :
  forall (X:Type) (R: relation X) (x y : X),
    clos_refl_trans R x y <-> clos_refl_trans_1n R x y.
Proof.
  intros X R x y.
  split.
  - intros Hrt.
    induction Hrt as [x y H | x | x y z _ IH1 _ IH2].
    + apply rsc_R. apply H.
    + apply rt1n_refl.
    + apply rsc_trans with y. apply IH1. apply IH2.
  - intros Hrt.
    induction Hrt as [x | x y z H _ IH].
    + apply rt_refl.
    + apply rt_trans with y.
      * apply rt_step. apply H.
      * apply IH.
Qed.
(** [] *)

(* 2022-08-08 17:13 *)


(* Exercise 5.16 *)

Definition my_le (n p : nat) :=
  forall P : nat -> Prop, P n -> (forall q : nat, P q -> P (S q)) -> P p.

Lemma my_le_n : forall n : nat, my_le n n.
Proof.
  unfold my_le.
  intros n P H H0.
  assumption.
Qed.

Lemma my_le_S : forall n p : nat, my_le n p -> my_le n (S p).
Proof.
  unfold my_le.
  intros n p H P H0 H1.
  apply H1.
  apply H.
  assumption.
  intros q H2.
  apply H1.
  assumption.
Qed.

Lemma my_le_le : forall n p : nat, my_le n p -> n <= p.
Proof.
  unfold my_le.
  intros n p H.
  pattern p.
  apply H.
  apply le_n.
  intros q H0.
  apply le_S.
  assumption.
Qed.