1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
module type S =
sig
  include Map.S

  module Dom : Dom.S with type elt = key

  exception Clash of key

  val dom : 'a t -> Dom.t
  val keys : 'a t -> key list
  val from_list : (key * 'a) list -> 'a t
  val from_list2 : key list -> 'a list -> 'a t
  val adjoin : 'a t -> 'a t -> 'a t
  val disjoint_add : key -> 'a -> 'a t -> 'a t (* raises Clash *)
  val disjoint_union : 'a t -> 'a t -> 'a t (* raises Clash *)
  val disjoint_unions : 'a t list -> 'a t (* raises Clash *)
end

module Make(X : Map.OrderedType) : S with type key = X.t =
struct
  include Map.Make(X)

  module Dom = Dom.Make(X)

  exception Clash of key

  let dom env = List.fold_left (fun s (x, _) -> Dom.add x s) Dom.empty (bindings env)
  let keys env = List.map fst (bindings env)
  let from_list kxs = List.fold_left (fun env (k, x) -> add k x env) empty kxs
  let from_list2 ks xs = List.fold_left2 (fun env k x -> add k x env) empty ks xs
  let adjoin env1 env2 = union (fun _ x1 x2 -> Some x2) env1 env2
  let disjoint_union env1 env2 = union (fun k _ _ -> raise (Clash k)) env1 env2
  let disjoint_unions envs = List.fold_left disjoint_union empty envs
  let disjoint_add k x env = disjoint_union env (singleton k x)

end