Definition term_from_active_term (t: active_term) : term :=
let (f, lv) := t in
fapply f (map (@term_from_value _ _ _) lv).
Definition value_list_order (lv lv' : list value) : Prop :=
suml (map (@value_size _) lv) < suml (map (@value_size _) lv').

(* Specifications: *)
Lemma value_list_order_wf : well_founded value_list_order.
Definition unify_list
(s : list (variable * value)) (lv : list value) (lp : list pattern) :
option (variable -> value) :=
option_map (assoc_default (variable_beq variable_eq_dec) value_default) (unify_list_aux s lv lp).
Lemma unify_list_unify_unify_list :
forall s s' v lv p lp,
unify_list_aux s (v :: lv) (p :: lp) = Some s' ->
exists s'', unify s v p = Some s'' /\ unify_list_aux s'' lv lp = Some s'.
Lemma unify_list_length :
forall s s' lv lp, unify_list_aux s lv lp = Some s' -> length lv = length lp.
Lemma unify_cons_eq_unify_list :
forall s s' c lv c' lp',
unify s (c_capply c lv) (p_capply c' lp') = Some s' ->
c = c' /\ unify_list_aux s lv lp' = Some s'.
Lemma unify_list_aux_extension lv lp s s':
unify_list_aux s lv lp = Some s' ->
exists s'',
s' = s'' ++ s /\
forall x, assoc (variable_beq variable_eq_dec) x s <> None -> assoc (variable_beq variable_eq_dec) x s'' = None.
Lemma unify_all_vars_defined :
forall (s s': list (variable * value)) (v: value) (p: pattern),
unify s v p = Some s' ->
forall x, In x (vars_of_pattern p) -> assoc (variable_beq variable_eq_dec) x s' <> None.
Lemma eq_psubst_consistent_assoc_extension :
forall s s' p,
(forall x, assoc (variable_beq variable_eq_dec) x s <> None -> assoc (variable_beq variable_eq_dec) x s' = None) ->
(forall x, In x (vars_of_pattern p) -> assoc (variable_beq variable_eq_dec) x s <> None) ->
psubst (assoc_default (variable_beq variable_eq_dec) value_default (s' ++ s)) p =
psubst (assoc_default (variable_beq variable_eq_dec) value_default s) p.
Lemma unify_sound :
forall (s s': list (variable * value)) (v: value) (p: pattern),
unify s v p = Some s' ->
psubst (assoc_default (variable_beq variable_eq_dec) value_default s') p = v.
Lemma psubst_app p v (s s' : list (variable * value)) :
(forall x : variable, assoc (variable_beq variable_eq_dec) x s <> None -> assoc (variable_beq variable_eq_dec) x s' = None) ->
(forall x, In x (vars_of_pattern p) -> assoc (variable_beq variable_eq_dec) x s <> None) ->
psubst (assoc_default (variable_beq variable_eq_dec) value_default s        ) p = v ->
psubst (assoc_default (variable_beq variable_eq_dec) value_default (s' ++ s)) p = v.
Lemma unify_list_sound :
forall (lp : list pattern) (lv : list value) (s : variable -> value),
unify_list [] lv lp = Some s -> map (psubst s) lp = lv.