(* ---------------------------------------------------------------------- *)
(** **** Properties of binds *)

(* Specifications: *)
(** Binds and empty. *)
Theorem binds_empty : forall A x (v : A),
x ∹ v ⋲ (@empty A) ->
False.
(** Binds on singular(s). *)
Theorem binds_single : forall A x y (v w : A),
x = y -> v = w ->
x ∹ v ⋲ (y ∶ w).
Theorem binds_single_inv : forall A x y (v w: A),
x ∹ v ⋲ (y ∶ w) ->
x = y ∧ v = w.
Theorem binds_singles : forall A x y (v w : A) ys (ws : list A),
x = y -> v = w ->
x ∹ v ⋲ (y :: ys ∷ w :: ws).
Theorem binds_singles_inv : forall A x y (v w : A) ys (ws : list A),
x ∹ v ⋲ (y :: ys ∷ w :: ws) ->
(x = y ∧ v = w) ∨ (x ∹ v ⋲ (ys ∷ ws)).
(** Binds is functional. *)
Theorem binds_eq_inv : forall A x (v w : A) (E : gen_env A),
x ∹ v ⋲ E -> x ∹ w ⋲ E ->
v = w.
(** Binds and concatenation. *)
Theorem binds_concat_r : forall A x (v : A) (F G : gen_env A),
x ∹ v ⋲ G ->
x ∹ v ⋲ (F & G).
Theorem binds_concat_l : forall A x (v : A) (F G : gen_env A),
x ∹ v ⋲ F ->
x ∉ G ->
x ∹ v ⋲ (F & G).
Theorem binds_concat_inv : forall A x (v : A) (F G : gen_env A),
x ∹ v ⋲ (F & G) ->
x ∹ v ⋲ G ∨ (x ∉ G ∧ x ∹ v ⋲ F).
(** Binds and belongs. *)
Theorem binds_belongs : forall A x (v : A) (F : gen_env A),
x ∹ v ⋲ F ->
x ∈ F.
Theorem belongs_binds : forall A x (F : gen_env A),
x ∈ F ->
exists v, x ∹ v ⋲ F.
(** Binds and map. *)
Theorem binds_map : forall A B x (v : A) (E : gen_env A) (f : A -> B),
x ∹ v ⋲ E ->
x ∹ (f v) ⋲ (map f E).
Theorem binds_map_inv : forall A B x (w : B) (E : gen_env A) (f : A -> B),
x ∹ w ⋲ (map f E) ->
exists v, x ∹ v ⋲ E /\ w = f v.
(** Binds and update_one. *)
Theorem binds_update_one_neq : forall A x y (v w : A) (F : gen_env A),
x ∹ v ⋲ F ->
x <> y ->
x ∹ v ⋲ (F [y <- w]).
Theorem binds_update_one_eq : forall A x y (v w : A) (F : gen_env A),
x ∈ F ->
x = y -> v = w ->
x ∹ v ⋲ (F [y <- w]).
Theorem binds_update_one_inv : forall A x y (v w : A) (F : gen_env A),
x ∹ v ⋲ (F [y <- w]) ->
(x <> y ∧ x ∹ v ⋲ F) ∨ (x ∈ F ∧ x = y ∧ v = w).
(** Binds and update. *)
Theorem binds_update_notin : forall A x (v : A) (F G : gen_env A),
x ∹ v ⋲ F ->
x ∉ G ->
x ∹ v ⋲ (F ::= G).
Theorem binds_update_in : forall A x (v : A) (F G : gen_env A),
x ∈ F ->
x ∹ v ⋲ G ->
x ∹ v ⋲ (F ::= G).
Theorem binds_update_self : forall A x (v : A) (F : gen_env A),
x ∈ F ->
x ∹ v ⋲ (F ::= (x ∶ v)).
Theorem binds_update_inv : forall A x (v : A) (F G : gen_env A),
x ∹ v ⋲ (F ::= G) ->
(x ∉ G ∧ x ∹ v ⋲ F) ∨ (x ∈ F ∧ x ∹ v ⋲ G).
(** Binds and remove. *)
Theorem binds_remove : forall A x y (v : A) (E : gen_env A),
x <> y -> x ∹ v ⋲ E ->
x ∹ v ⋲ (E ∖ {y}).
Theorem binds_remove_inv : forall A x y (v : A) (E : gen_env A),
x <> y -> x ∹ v ⋲ (E ∖ {y}) ->
x ∹ v ⋲ E.
Theorem binds_all_remove : forall A x ys (v : A) (E : gen_env A),
¬ List.In x ys -> x ∹ v ⋲ E ->
x ∹ v ⋲ (E ∖ ys).
Theorem binds_all_remove_inv : forall A x ys (v : A) (E : gen_env A),
¬ List.In x ys -> x ∹ v ⋲ (E ∖ ys) ->
x ∹ v ⋲ E.
(** Binds and ok. *)
Theorem binds_concat_ok_comm : forall A x (v : A) (F G : gen_env A),
binds x v (F & G) ->
ok (F & G) ->
binds x v (G & F).
(** Decidability of binds. *)
Theorem binds_dec_exists : forall A x (E : gen_env A),
{ v | x ∹ v ⋲ E } + { forall v, ¬ x ∹ v ⋲ E }.
Theorem binds_dec : forall A x (v : A) (E : gen_env A),
(forall w w' : A, { w = w' } + { ¬ w = w' }) ->
{ x ∹ v ⋲ E } + { ¬ x ∹ v ⋲ E }.