Merge branch 'cleaning_again_example_sin_cos' into 'master'
[why3.git] / stdlib / fmap.mlw
blobe26763942b0e4698f7036cd5c1cbac11e6b83160
2 (** {1 Finite Maps} *)
4 (** {2 Polymorphic maps to be used in spec/ghost only} *)
6 module Fmap
8   use int.Int
9   use map.Map
10   use set.Fset as S
12   type fmap 'k 'v = abstract {
13     contents: 'k -> 'v;
14       domain: S.fset 'k;
15   }
16   meta coercion function contents
18   predicate (==) (m1 m2: fmap 'k 'v) =
19     S.(==) m1.domain m2.domain /\
20     forall k. S.mem k m1.domain -> m1[k] = m2[k]
22   axiom extensionality:
23     forall m1 m2: fmap 'k 'v. m1 == m2 -> m1 = m2
25   predicate mem (k: 'k) (m: fmap 'k 'v) =
26     S.mem k m.domain
28   predicate mapsto (k: 'k) (v: 'v) (m: fmap 'k 'v) =
29     mem k m /\ m[k] = v
31   lemma mem_mapsto:
32     forall k: 'k, m: fmap 'k 'v. mem k m -> mapsto k m[k] m
34   predicate is_empty (m: fmap 'k 'v) =
35     S.is_empty m.domain
37   function mk (d: S.fset 'k) (m: 'k -> 'v) : fmap 'k 'v
39   axiom mk_domain:
40     forall d: S.fset 'k, m: 'k -> 'v. domain (mk d m) = d
42   axiom mk_contents:
43     forall d: S.fset 'k, m: 'k -> 'v, k: 'k.
44     S.mem k d -> (mk d m)[k] = m[k]
46   constant empty: fmap 'k 'v
48   axiom is_empty_empty: is_empty (empty: fmap 'k 'v)
50   function add (k: 'k) (v: 'v) (m: fmap 'k 'v) : fmap 'k 'v
52   function ([<-]) (m: fmap 'k 'v) (k: 'k) (v: 'v) : fmap 'k 'v =
53     add k v m
55   (*FIXME? (add k v m).contents = m.contents[k <- v] *)
57   axiom add_contents_k:
58     forall k v, m: fmap 'k 'v. (add k v m)[k] = v
60   axiom add_contents_other:
61     forall k v, m: fmap 'k 'v, k1. mem k1 m -> k1 <> k -> (add k v m)[k1] = m[k1]
63   axiom add_domain:
64     forall k v, m: fmap 'k 'v. (add k v m).domain = S.add k m.domain
66   (* FIXME? find_opt (k: 'k) (m: fmap 'k 'v) : option 'v *)
68   function find (k: 'k) (m: fmap 'k 'v) : 'v
70   axiom find_def:
71     forall k, m: fmap 'k 'v. mem k m -> find k m = m[k]
73   function remove (k: 'k) (m: fmap 'k 'v) : fmap 'k 'v
75   axiom remove_contents:
76     forall k, m: fmap 'k 'v, k1. mem k1 m -> k1 <> k -> (remove k m)[k1] = m[k1]
78   axiom remove_domain:
79     forall k, m: fmap 'k 'v. (remove k m).domain = S.remove k m.domain
81   function size (m: fmap 'k 'v) : int =
82     S.cardinal m.domain
84 end
86 (** {2 Finite monomorphic maps to be used in programs only}
88 A program function `eq` deciding equality on the `key` type must be provided when cloned.
91 (** {3 Applicative maps} *)
93 module MapApp
95   use int.Int
96   use map.Map
97   use export Fmap
99   type key
101   (* we enforce type `key` to have a decidable equality
102      by requiring the following function *)
103   val eq (x y: key) : bool
104     ensures { result <-> x = y }
106   type t 'v = abstract {
107     to_fmap: fmap key 'v;
108   }
109   meta coercion function to_fmap
111   val create () : t 'v
112     ensures { result.to_fmap = empty }
114   val mem (k: key) (m: t 'v) : bool
115     ensures { result <-> mem k m }
117   val is_empty (m: t 'v) : bool
118     ensures { result <-> is_empty m }
120   val add (k: key) (v: 'v) (m: t 'v) : t 'v
121     ensures { result = add k v m }
123   val find (k: key) (m: t 'v) : 'v
124     requires { mem k m }
125     ensures  { result = m[k] }
126     ensures  { result = find k m }
128   use ocaml.Exceptions
130   val find_exn (k: key) (m: t 'v) : 'v
131     ensures { S.mem k m.domain }
132     ensures { result = m[k] }
133     raises  { Not_found ->  not (S.mem k m.domain) }
135   val remove (k: key) (m: t 'v) : t 'v
136     ensures { result = remove k m }
138   val size (m: t 'v) : int
139     ensures { result = size m }
143 (** {3 Applicative maps of integers} *)
145 module MapAppInt
147   use int.Int
149   clone export MapApp with type key = int, val eq = Int.(=)
153 (** {3 Imperative maps} *)
155 module MapImp
157   use int.Int
158   use map.Map
159   use export Fmap
161   type key
163   val eq (x y: key) : bool
164     ensures { result <-> x = y }
166   type t 'v = abstract {
167     mutable to_fmap: fmap key 'v;
168   }
169   meta coercion function to_fmap
171   val create () : t 'v
172     ensures { result.to_fmap = empty }
174   val mem (k: key) (m: t 'v) : bool
175     ensures { result <-> mem k m }
177   val is_empty (m: t 'v) : bool
178     ensures { result <-> is_empty m }
180   val add (k: key) (v: 'v) (m: t 'v) : unit
181     writes  { m }
182     ensures { m = add k v (old m) }
184   val find (k: key) (m: t 'v) : 'v
185     requires { mem k m }
186     ensures  { result = m[k] }
187     ensures  { result = find k m }
189   use ocaml.Exceptions
191   val find_exn (k: key) (m: t 'v) : 'v
192     ensures { S.mem k m.domain }
193     ensures { result = m[k] }
194     raises  { Not_found ->  not (S.mem k m.domain) }
196   val remove (k: key) (m: t 'v) : unit
197     writes  { m }
198     ensures { m = remove k (old m) }
200   val size (m: t 'v) : int
201     ensures { result = size m }
203   val clear (m: t 'v) : unit
204     writes  { m }
205     ensures { m = empty }
209 (** {3 Imperative maps of integers} *)
211 module MapImpInt
213   use int.Int
215   clone export MapImp with type key = int, val eq = Int.(=)