Set Implicit Arguments.
(* Application to values & terms. *)
Inductive my_term :=
| MyTValue: my_value -> my_term
| MyTApp: my_term -> my_term -> my_term
with my_value :=
| MyVVar: nat -> my_value
| MyVAbs: my_term -> my_value.
Instance Var_my_value : Var my_value := {
var := MyVVar
}.
Fixpoint traverse_my_term (f : nat -> nat -> my_value) l t :=
match t with
| MyTValue v =>
MyTValue (traverse_my_value f l v)
| MyTApp t1 t2 =>
MyTApp (traverse_my_term f l t1) (traverse_my_term f l t2)
end
with traverse_my_value f l v :=
match v with
| MyVVar x =>
f l x
| MyVAbs t =>
MyVAbs (traverse_my_term f (1 + l) t)
end.
Instance Traverse_my_value_my_value : Traverse my_value my_value := {
traverse := traverse_my_value
}.
Instance Traverse_my_value_my_term : Traverse my_value my_term := {
traverse := traverse_my_term
}.
(* TEMPORARY It is unfortunate that we have to first prove two mutually dependent lemmas using [Lemma ... with ...], then write down two independent [Instance] declarations. I would prefer to be able to directly write two mutually depdendent instance declarations, using [Instance ... with ...]. Here, I am forced to duplicate the statement of the properties of interest, which is unpleasant. *)
Instance TraverseVarInjective_my_value_my_value :
@TraverseVarInjective my_value _ my_value _.
Instance TraverseVarInjective_my_value_my_term :
@TraverseVarInjective my_value _ my_term _.
Instance TraverseFunctorial_my_value_my_value : @TraverseFunctorial my_value _ my_value _.
Instance TraverseRelative_my_value_my_value : @TraverseRelative my_value my_value _.
Instance TraverseRelative_my_value_my_term : @TraverseRelative my_value my_term _.
Instance TraverseVarIsIdentity_my_value_my_value : @TraverseVarIsIdentity my_value _ my_value _.
Instance TraverseVarIsIdentity_my_value_my_term : @TraverseVarIsIdentity my_value _ my_term _.

Lemma lift_MyVAbs:
forall w k t,
lift w k (MyVAbs t) = MyVAbs (lift w (1 + k) t).