(** The [auto] tactic frees us from this drudgery by _searching_ for a sequence of applications that will prove the goal *)
Example auto_example_1' : forall (P Q R: Prop),
(P -> Q) -> (Q -> R) -> P -> R.
(** The [auto] tactic solves goals that are solvable by any combination of - [intros] and - [apply] (of hypotheses from the local context, by default). *)
(** Using [auto] is always "safe" in the sense that it will never fail and will never change the proof state: either it completely solves the current goal, or it does nothing. *)
(** Here is a more interesting example showing [auto]'s power: *)
Example auto_example_2 : forall P Q R S T U : Prop,
(P -> Q) ->
(P -> R) ->
(T -> R) ->
(S -> T -> U) ->
((P->Q) -> (P->S)) ->
T ->
P ->
U.
(** When searching for potential proofs of the current goal, [auto] considers the hypotheses in the current context together with a _hint database_ of other lemmas and constructors.  Some common lemmas about equality and logical operators are installed in this hint database by default. *)
Example auto_example_4 : forall P Q R : Prop,
Q ->
(Q -> R) ->
P \/ (Q /\ R).
(** Of course, in any given development there will probably be some specific constructors and lemmas that are used very often in proofs.  We can add these to the global hint database by writing  Hint Resolve T.  at the top level, where [T] is a top-level theorem or a constructor of an inductively defined proposition (i.e., anything whose type is an implication).  As a shorthand, we can write  Hint Constructors c.  to tell Coq to do a [Hint Resolve] for _all_ of the constructors from the inductive definition of [c].  It is also sometimes necessary to add  Hint Unfold d.  where [d] is a defined symbol, so that [auto] knows to expand uses of [d], thus enabling further possibilities for applying lemmas that it knows about. *)
Hint Resolve le_antisym.
Example auto_example_6' : forall n m p : nat,
(n<= p -> (n <= m /\ m <= n)) ->
n <= p ->
n = m.
Definition is_fortytwo x := x = 42.
Example auto_example_7: forall x, (x <= 42 /\ 42 <= x) -> is_fortytwo x.
(** When we are using a particular tactic many times in a proof, we can use a variant of the [Proof] command to make that tactic into a default within the proof.  Saying [Proof with t] (where [t] is an arbitrary tactic) allows us to use [t1...] as a shorthand for [t1;t] within the proof.  As an illustration, here is an alternate version of the previous proof, using [Proof with auto]. *)

Theorem ceval_deterministic'_alt: forall c st st1 st2,
c / st \\ st1  ->
c / st \\ st2 ->
st1 = st2.