Fixpoint max_arity_pattern (p : pattern) : nat :=
  match p with
  | p_var _ => 0
  | p_capply _ lp => max (length lp) (maxl (map max_arity_pattern lp))
  end.Fixpoint max_arity_term (t : term) : nat :=
  match t with
    | var _ => 0
    | capply _ lt => max (length lt) (maxl (map max_arity_term lt))
    | fapply _ lt => max (length lt) (maxl (map max_arity_term lt))
  end.Definition max_arity_rule (r : rule) : nat :=
  match r with
  | rule_intro _ lp t => max (max_arity_term t) (max (length lp) (maxl (map max_arity_pattern lp)))
  end.Definition max_arity_prog (prog : list rule) : nat :=
  maxl (map max_arity_rule prog).Definition rule_vars_defined (r : rule) : Prop :=
  match r with
  | rule_intro _ lp t => incl (vars_of_term t) (flat_map vars_of_pattern lp)
  end.Definition wf_prog (prog : list rule) : Prop :=
  andl (map rule_vars_defined prog) /\ max_arity_prog prog <= max_arity.Fixpoint subst (s : variable -> value)(t : term) : term :=
  match t with
  | var x => s x
  | capply c lt => capply c (map (subst s) lt)
  | fapply f lt => fapply f (map (subst s) lt)
  end.Fixpoint psubst (s : variable -> value)(p : pattern) : value :=
  match p with
  | p_var x => s x
  | p_capply c lp => c_capply c (map (psubst s) lp)
  end.

Lemma subst_psubst s p : subst s (term_from_pattern p) = term_from_value (psubst s p).