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. *)

(* Specifications: *)
Lemma traverse_my_value_injective:
forall f,
(forall x1 x2 l, f l x1 = f l x2 -> x1 = x2) ->
forall (t1 t2 : my_value) l,
traverse_var f l t1 = traverse_var f l t2 ->
t1 = t2
with traverse_my_term_injective:
forall f,
(forall x1 x2 l, f l x1 = f l x2 -> x1 = x2) ->
forall (t1 t2 : my_term) l,
traverse_var f l t1 = traverse_var f l t2 ->
t1 = t2.