(** Exercise [subst_fresh] To show the ease of reasoning with these definitions, we will prove a standard result from lambda calculus: if a variable does not appear free in a term, then substituting for it has no effect.  HINTS: Prove this lemma by induction on [e].  - You will need to use [simpl] in many cases.  You can [simpl] everything everywhere (including hypotheses) with the pattern [simpl in *].  - Part of this proof includes a false assumption about free variables.  Destructing this hypothesis produces a goal about finite set membership that is solvable by [fsetdec]. *)

(* Specifications: *)
Lemma subst_fresh : forall (x : atom) e u,
x `notin` fv e -> [x ~> u] e = e.
(* Take-home Demo: Prove that free variables are not introduced by substitution.  This proof actually is very automatable ([simpl in *; auto.] takes care of all but the fvar case), but the explicit proof below demonstrates two parts of the finite set library. These two parts are the tactic [destruct_notin] and the lemma [notin_union], both defined in the module [FSetWeakNotin].  Before stepping through this proof, you should go to that module to read about those definitions and see what other finite set reasoning is available.  *)
Lemma subst_notin_fv : forall x y u e,
x `notin` fv e -> x `notin` fv u ->
x `notin` fv ([y ~> u]e).
Lemma subst_fresh : forall (x : atom) e u,
x `notin` fv e -> [x ~> u] e = e.