(* ---------------------------------------------------------------------- *)
(** **** Properties of update *)

(* Specifications: *)
(** Update is identity in presence of empty environments. *)
Axiom update_empty_r : forall A (E : gen_env A),
E ::= (@empty A) = E.
Axiom update_empty_l : forall A (E : gen_env A),
(@empty A) ::= E = (@empty A).
(** Update with single. *)
Axiom update_update_one : forall A x (v : A) (E : gen_env A),
E ::= (x ∶ v) = E [x <- v].
Axiom update_single_single : forall A x y (v w : A),
x = y ->
(x ∶ v) ::= (y ∶ w) = (x ∶ w).
Axiom update_single_single_neq : forall A x y (v w : A),
x <> y ->
(x ∶ v) ::= (y ∶ w) = (x ∶ v).
(** Update commutes with concatenation on the right. *)
Axiom update_concat_r : forall A (E F G : gen_env A),
E ::= (F & G) = (E ::= F) ::= G.
(** Dom is unchanged by updating. *)
Axiom dom_update : forall A (E F : gen_env A),
dom (E ::= F) = dom E.
(** Belongs commutes with update. *)
Axiom belongs_update : forall A x (E F : gen_env A),
x ∈ E ->
x ∈ (E ::= F).
Axiom belongs_update_inv : forall A x (E F : gen_env A),
x ∈ (E ::= F) ->
x ∈ E.
(** All_belongs commutes with update. *)
Axiom all_belongs_update : forall A xs (E F : gen_env A),
xs ⊂ E ->
xs ⊂ (E ::= F).
Axiom all_belongs_update_inv : forall A xs (E F : gen_env A),
xs ⊂ (E ::= F) ->
xs ⊂ E.
(** Notin commutes with update. *)
Axiom notin_update : forall A x (E F : gen_env A),
x ∉ E ->
x ∉ (E ::= F).
Axiom notin_update_inv : forall A x (E F : gen_env A),
x ∉ (E ::= F) ->
x ∉ E.
(** All_notin commutes with update. *)
Axiom all_notin_update : forall A xs (E F : gen_env A),
xs ⊄ E ->
xs ⊄ (E ::= F).
Axiom all_notin_update_inv : forall A xs (E F : gen_env A),
xs ⊄ (E ::= F) ->
xs ⊄ E.
(** Update is identity when the domains are disjoints. *)
Axiom update_notin : forall A (E F : gen_env A),
(dom F) ⊄ E ->
E ::= F = E.
(** Update commutes with map. *)
Axiom map_update : forall A B (f : A -> B) (E F : gen_env A),
map f (E ::= F) = (map f E) ::= (map f F).
(** Ok commutes with update. *)
Axiom ok_update : forall A (E F : gen_env A),
ok E ->
ok (E ::= F).
Axiom ok_update_inv : forall A (E F : gen_env A),
ok (E ::= F) ->
ok E.
Lemma update_empty_r : forall E,
E ::= (@empty A) = E.
Lemma update_update_one : forall x v E,
E ::= (x ∶ v) = E [x <- v].
Lemma dom_update : forall E F,
dom (E ::= F) = dom E.
Lemma belongs_update : forall x E F,
x ∈ E ->
x ∈ (E ::= F).
Lemma belongs_update_inv : forall x E F,
x ∈ (E ::= F) ->
x ∈ E.
Lemma all_belongs_update : forall xs E F,
xs ⊂ E ->
xs ⊂ (E ::= F).
Lemma all_belongs_update_inv : forall xs E F,
xs ⊂ (E ::= F) ->
xs ⊂ E.
Lemma notin_update : forall x E F,
x ∉ E ->
x ∉ (E ::= F).
Lemma notin_update_inv : forall x E F,
x ∉ (E ::= F) ->
x ∉ E.
Lemma all_notin_update : forall xs E F,
xs ⊄ E ->
xs ⊄ (E ::= F).
Lemma all_notin_update_inv : forall xs E F,
xs ⊄ (E ::= F) ->
xs ⊄ E.
Lemma update_notin : forall E F,
(dom F) ⊄ E ->
E ::= F = E.
Lemma map_update : forall f E F,
map f (E ::= F) = (map f E) ::= (map f F).
Lemma ok_update : forall E F,
ok E ->
ok (E ::= F).
Lemma ok_update_inv : forall E F,
ok (E ::= F) ->
ok E.