Definition rule_subst_of_cbv_function (proof_tree : cbv) : nat * (variable -> value) :=
  match proof_tree with
  | cbv_function i s _ _ _ => (i, s)
  | _ => (0, subst_default) (* impossible case *)
  end.Definition proj_left (proof_tree : cbv) : term :=
  match proof_tree with
    | cbv_constr _ t _ => t
    | cbv_split _ _ t _ => t
    | cbv_function _ _ _ t _ => t
  end.Definition proj_right (proof_tree : cbv) : value :=
  match proof_tree with
    | cbv_constr _ _ v => v
    | cbv_split _ _ _ v => v
    | cbv_function _ _ _ _ v => v
  end.Fixpoint wf (proof_tree : cbv) : Prop :=
  match proof_tree with
    | cbv_constr l (capply c lt) (c_capply c' lv) =>
        c = c' /\
        lt = map proj_left l /\ lv = map proj_right l /\ (* Permutations would also be acceptable *)
        andl (map wf l)
    | cbv_split l ((cbv_function _ _ _ (fapply f lv) v) as p) (fapply f' lt) v' =>
        lt = map proj_left l /\ lv = map (@term_from_value _ _ _)(map proj_right l) /\
        andl (map wf l) /\
        f = f' /\ v = v' /\
        wf p
    | cbv_function i s p (fapply f lv) v =>
        exists lp t,
        i < length prog /\
        nth i prog rule_default = rule_intro f lp t /\
        lv = map (@term_from_value _ _ _) (map (psubst s) lp) /\
        proj_left p = subst s t /\ proj_right p = v /\
        wf p
    | _ => False
  end.

(* Specifications: *)
Lemma wf_cbv_function i s p t v : wf (cbv_function i s p t v) -> wf p.
Lemma wf_InCBV_wf p proof_tree: wf proof_tree -> InCBV p proof_tree -> wf p.