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]. *)
Hint Resolve agree_concat : agree.
(* Concatenation and insertion commute. *)
(* [replicate n a] is a list of [n] elements, all of which are equal to [a]. *)
Fixpoint replicate (A : Type) (n : nat) (a : A) : list A :=
match n with
| 0 =>
@nil _
| S n =>
cons a (replicate n a)
end.
(* The list [replicate n a] has length [n]. *)
(* A special case of [insert_concat]. *)
(* [concat . (replicate . a)] is just an iterated version of [insert . a]. *)
Hint Resolve insert_concat length_replicate insert_concat_replicate
concat_replicate_is_iterated_insert : insert_concat.
(* A special case of [length_concat]. *)

Lemma length_concat_replicate:
forall A (a : A) (e1 : env A) n1 n2 n,
length e1 <= n1 ->
n1 + n2 = n ->
length (concat e1 (replicate n2 a)) <= n.