(** 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 a piece of evidence. *)
(** 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) : ev 4 *)
Print ev_4'.
(* ===> ev_4'   =   ev_SS 2 (ev_SS 0 ev_0) : ev 4 *)
Print ev_4''.
(* ===> ev_4''  =   ev_SS 2 (ev_SS 0 ev_0) : ev 4 *)
Print ev_4'''.
(* ===> ev_4''' =   ev_SS 2 (ev_SS 0 ev_0) : ev 4 *)
(** **** Exercise: 1 star (eight_is_even)  *)
(** Give a tactic proof and a proof object showing that [ev 8]. *)

(* Specifications: *)
Theorem ev_8 : ev 8.
Definition ev_plus4' : forall n, ev n -> ev (4 + n) :=
fun (n : nat) => fun (H : ev n) =>
ev_SS (S (S n)) (ev_SS n H).