(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

(* The following definitions allow us to use the [DeBruijn] library. In
   particular, [traverse_term] defines the binding structure of terms. *)

Instance Var_term : Var term := {
  var := TVar (* avoid eta-expansion *)
}.Fixpoint traverse_term (f : nat -> nat -> term) l t :=
  match t with
  | TVar x =>
      f l x
  | TAbs t =>
      TAbs (traverse_term f (1 + l) t)
  | TApp t1 t2 =>
      TApp (traverse_term f l t1) (traverse_term f l t2)
  end.Instance Traverse_term : Traverse term term := {
  traverse := traverse_term
}.Instance TraverseVarInjective_term : @TraverseVarInjective term _ term _.Instance TraverseFunctorial_term : @TraverseFunctorial term _ term _.Instance TraverseRelative_term : @TraverseRelative term term _.Instance TraverseIdentifiesVar_term : @TraverseIdentifiesVar term _ _.Instance TraverseVarIsIdentity_term : @TraverseVarIsIdentity term _ term _.

Lemma subst_TAbs: forall v k t, subst v k (TAbs t) = TAbs (subst (shift 0 v) (1 + k) t).