Definition empty : gen_env A := nil.Definition single x v := (x, v) :: nil.Fixpoint singles xs vs : gen_env A :=
  match xs, vs with
    | x :: xs, v :: vs => (x, v) :: (singles xs vs)
    | _, _ => nil
  end.Definition concat E F := F ++ E.Fixpoint get x E : option A :=
  match E with
    | nil => None
    | (y, v) :: E' => if eq_keys_dec x y then Some v else get x E'
  end.Fixpoint dom E : list TVar :=
  match E with
    | nil => nil
    | (x, _) :: E' => x :: (dom E')
  end.Fixpoint img E : list A :=
  match E with
    | nil => nil
    | (_, v) :: E' => v :: (img E')
  end.Definition belongs x E :=
  List.In x (dom E).Definition all_belongs xs E :=
  forall x, List.In x xs -> belongs x E.Definition notin x E := 
  ~ belongs x E.Definition all_notin xs E :=
  forall x, List.In x xs -> notin x E.Fixpoint map f E : gen_env B :=
  match E with
    | nil => nil
    | (x, v) :: E' => (x, f v) :: map f E'
  end.Fixpoint update_one E x v : gen_env A :=
  match E with
    | nil => nil
    | (y, v') :: E' =>
      if eq_keys_dec x y then (y, v) :: E'
        else (y, v') :: (update_one E' x v)
  end.Fixpoint update E F : gen_env A :=
  match F with
    | nil => E
    | (x, v) :: F' => update_one (update E F') x v
  end.Fixpoint remove x E : gen_env A :=
  match E with
    | nil => nil
    | (y, v) :: E => if eq_keys_dec x y then E else (y, v) :: (remove x E)
  end.Fixpoint all_remove xs E : gen_env A :=
  match xs with
    | nil => E
    | x :: xs => all_remove xs (remove x E)
  end.Inductive ok : gen_env A -> Prop :=
| ok_nil : ok nil
| ok_cons : forall x v F, ok F ∧ notin x F -> ok (concat F (single x v))
.Inductive ok : gen_env A -> Prop :=
| ok_nil : ok nil
| ok_cons : forall x v F, ok F ∧ notin x F -> ok (concat F (single x v))
.Inductive ok : gen_env A -> Prop :=
| ok_nil : ok nil
| ok_cons : forall x v F, ok F ∧ notin x F -> ok (concat F (single x v))
.(** [x ∶ v] is the notation for a singleton environment mapping x to v. *)

Notation "x '∶' v" := (single x v)
  (at level 63) : gen_env_scope.(** [xs ∷ vs] is the notation for an environment mapping xs to vs. *)

Notation "xs '∷' vs" := (singles xs vs)
  (at level 63) : gen_env_scope.(** [E & F] is the notation for concatenation of E and F. *)

Notation "E '&' F" := (concat E F) 
  (at level 65, left associativity) : gen_env_scope.(** [E ∖ { x } ] is the notation for removing x from E. *)

Notation "E '∖' '{' x '}'" := (remove x E) 
  (at level 64, left associativity) : gen_env_scope.(** [E ∖ xs ] is the notation for removing xs from E. *)

Notation "E '∖' xs" := (all_remove xs E) 
  (at level 64, left associativity) : gen_env_scope.(** [E '[' x '<-' v ']' ] is the notation for updating x in E with v. *)

Notation "E '[' x '<-' v ']'" := (update_one E x v) 
  (at level 65, left associativity) : gen_env_scope.(** [E ::= F] is the notation for updating of E with F. *)

Notation "E '::=' F" := (update E F) 
  (at level 65, left associativity) : gen_env_scope.(** [x ∈ E] to be read x is bound in E. *)

Notation "x '∈' E" := (belongs x E)
  (at level 67) : gen_env_scope.(** [xs ⊂ E] to be read xs are bound in E. *)

Notation "xs '⊂' E" := (all_belongs xs E)
  (at level 67) : gen_env_scope.(** [x '∉' E] to be read x is unbound in E. *)

Notation "x '∉' E" := (notin x E)
  (at level 67) : gen_env_scope.(** [xs '⊄' E] to be read xs are unbound in E. *)

Notation "xs '⊄' E" := (all_notin xs E)
  (at level 67) : gen_env_scope.

Lemma dom_concat : forall E F, dom (E & F) = List.app (dom F) (dom E).