Section CBV.
Variables variable function constructor : Type.
Variable variable_eq_dec : forall (x1 x2 : variable), {x1=x2}+{x1<>x2}.
Variable function_eq_dec : forall (x1 x2 : function), {x1=x2}+{x1<>x2}.
Variable constructor_eq_dec : forall (x1 x2 : constructor), {x1=x2}+{x1<>x2}.
Notation value := (Syntax.value constructor).
Notation term := (Syntax.term variable function constructor).
Notation pattern := (Syntax.pattern variable constructor).
Notation rule := (Syntax.rule variable function constructor).
Notation term_beq := (term_beq variable_eq_dec function_eq_dec constructor_eq_dec).
Definition cache : Type := list (term * value).
Notation assoc_cache := (assoc term_beq).
Definition cache_beq (C C' : cache) : bool :=
list_beq _ (prod_beq _ _ term_beq (value_beq constructor_eq_dec)) C C'.
Inductive cbv : Type :=
| cbv_constr : list cbv -> cache -> term -> cache -> value -> cbv
| cbv_split : list cbv -> cbv -> cache -> term -> cache -> value -> cbv
| cbv_update : nat -> (variable -> value) -> cbv -> cache -> term -> cache -> value -> cbv
| cbv_read : cache -> term -> value -> cbv.
(* Smarter induction principle than the one automatically generated *)

Lemma cbv_ind2 :
forall (P : cbv -> Prop),
(forall lp c1 t c2 v, (forall p, In p lp -> P p) -> P (cbv_constr lp c1 t c2 v)) ->
(forall lp p c1 t c2 v, (forall p, In p lp -> P p) -> P p -> P (cbv_split lp p c1 t c2 v)) ->
(forall n s p c1 t c2 v, P p -> P (cbv_update n s p c1 t c2 v)) ->
(forall c t v, P (cbv_read c t v)) ->
forall p, P p.