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).
Fixpoint value_size (v : value) : nat :=
match v with
| c_capply _ lv => 1 + suml (map value_size lv)
end.