Section Subsume.
Variable A : Type.
Variable sub : A -> A -> Prop.
Variable sub_reflexive:
forall a,
sub a a.
Variable sub_transitive:
forall a1 a2 a3,
sub a1 a2 ->
sub a2 a3 ->
sub a1 a3.
(* Subsumption is first extended to options. *)
Definition osub (o1 o2 : option A) :=
forall a2,
o2 = Some a2 ->
exists a1,
o1 = Some a1 /\ sub a1 a2.
(* Then, it is extended pointwise to environments. *)
Definition subsume (e1 e2 : env A) :=
forall x,
osub (lookup x e1) (lookup x e2).
(* Subsumption of environments is reflexive and transitive. *)
(* Every environment subsumes the empty environment. *)
(* Extending two environments with a new variable preserves subsumption. *)
(* Applying a transformation [f] pointwise to two environments preserves environment subsumption, provided [f] preserves [sub]. *)
End Subsume.
Hint Resolve osub_reflexive osub_Some_Some subsume_reflexive
subsume_transitive subsume_empty subsume_insert subsume_map : subsume.
(* ---------------------------------------------------------------------------- *)
(* Extending an environment with a list of bindings found in a pattern. *)
(* Note that we cannot define the concatenation of two environments, because we view environments as total functions, so we do not have precise control over their domain. Only a list has finite domain. *)
(* Concatenation is just an iterated version of [insert 0]. *)
Fixpoint concat (A : Type) (e1 : env A) (e2 : list A) : env A :=
match e2 with
| nil =>
e1
| cons a e2 =>
concat (insert 0 a e1) e2
end.
(* Concatenation acts upon the length of the environment in an obvious manner. *)
Hint Resolve length_concat : length construction_closed.
(* If [e1] and [e2] agree up to depth [k], then, after extending them with a common suffix [e], they agree up to depth [k + length e]. *)

Lemma agree_concat:
forall A (e : list A) (e1 e2 : env A) k n,
agree e1 e2 k ->
k + length e = n ->
agree (concat e1 e) (concat e2 e) n.