Inductive Forall2' (A B : Type) (R : A -> B -> Type) : list A -> list B -> Type :=
Forall2'_nil : Forall2' R [] []
| Forall2'_cons : forall (x : A) (y : B) (l : list A) (l' : list B),
R x y -> Forall2' R l l' -> Forall2' R (x :: l) (y :: l').

(* Specifications: *)
Lemma Forall2_trans_rel (A : Type) (R1 R2 : A -> A -> Prop) (l1 l2 : list A) : (forall x y, R1 x y -> R2 x y) -> Forall2 R1 l1 l2 -> Forall2 R2 l1 l2.
Lemma Forall2_product (A : Type) (R : A -> A -> Prop) (ls lt : list A) :
ls <>  [] -> Forall2 R ls lt -> product R ls lt.
Lemma Forall2_eq A (l1 l2 : list A) :
Forall2 eq l1 l2 -> l1 = l2.
Lemma evaluates_unique t v1 v2 :
evaluates t v1 ->
evaluates t v2 ->
v1 = v2.
Lemma evaluates_value v :
evaluates (term_from_value _ _ v) v.
Lemma In_nth:
forall (A : Type) (l : list A) (x d : A) n,
n < length l -> nth n l d = x -> x ∈ l.
Lemma evaluates_sound t v c:
(forall (t0 : term) (v0 : value), assoc_cache t0 c = Some v0
-> evaluates t0 v0 /\ max_arity_term (term_from_value variable function v0) <= max_arity) ->
evaluates t v ->
max_arity_term t <= max_arity ->
exists p, wf p /\ proj_right p = v /\ proj_left p = t /\ cache_left p = c /\
max_arity_term (term_from_value variable function v) <= max_arity /\
(forall t0 v0, assoc_cache t0 (cache_right p) = Some v0
-> evaluates t0 v0 /\ max_arity_term (term_from_value variable function v0) <= max_arity).
(* Simpler, weaker version *)
Lemma evaluates_sound' (t : term) (v : value):
evaluates t v ->
max_arity_term t <= max_arity ->
exists p, wf p /\ proj_right p = v /\ proj_left p = t.