54 "fib_step 0 = (Suc 0, 0)" |
54 "fib_step 0 = (Suc 0, 0)" |
55 "fib_step (Suc n) = (let (m, q) = fib_step n in (m + q, m))" |
55 "fib_step (Suc n) = (let (m, q) = fib_step n in (m + q, m))" |
56 by (simp_all add: fib_step_def) |
56 by (simp_all add: fib_step_def) |
57 |
57 |
58 text \<open> |
58 text \<open> |
59 \noindent What remains is to implement @{const fib} by @{const |
59 \noindent What remains is to implement \<^const>\<open>fib\<close> by \<^const>\<open>fib_step\<close> as follows: |
60 fib_step} as follows: |
|
61 \<close> |
60 \<close> |
62 |
61 |
63 lemma %quote [code]: |
62 lemma %quote [code]: |
64 "fib 0 = 0" |
63 "fib 0 = 0" |
65 "fib (Suc n) = fst (fib_step n)" |
64 "fib (Suc n) = fst (fib_step n)" |
108 "AQueue xs ys = Queue (ys @ rev xs)" |
107 "AQueue xs ys = Queue (ys @ rev xs)" |
109 |
108 |
110 code_datatype %quote AQueue |
109 code_datatype %quote AQueue |
111 |
110 |
112 text \<open> |
111 text \<open> |
113 \noindent Here we define a \qt{constructor} @{const "AQueue"} which |
112 \noindent Here we define a \qt{constructor} \<^const>\<open>AQueue\<close> which |
114 is defined in terms of \<open>Queue\<close> and interprets its arguments |
113 is defined in terms of \<open>Queue\<close> and interprets its arguments |
115 according to what the \emph{content} of an amortised queue is supposed |
114 according to what the \emph{content} of an amortised queue is supposed |
116 to be. |
115 to be. |
117 |
116 |
118 The prerequisite for datatype constructors is only syntactical: a |
117 The prerequisite for datatype constructors is only syntactical: a |
145 |
144 |
146 text \<open> |
145 text \<open> |
147 \noindent It is good style, although no absolute requirement, to |
146 \noindent It is good style, although no absolute requirement, to |
148 provide code equations for the original artefacts of the implemented |
147 provide code equations for the original artefacts of the implemented |
149 type, if possible; in our case, these are the datatype constructor |
148 type, if possible; in our case, these are the datatype constructor |
150 @{const Queue} and the case combinator @{const case_queue}: |
149 \<^const>\<open>Queue\<close> and the case combinator \<^const>\<open>case_queue\<close>: |
151 \<close> |
150 \<close> |
152 |
151 |
153 lemma %quote Queue_AQueue [code]: |
152 lemma %quote Queue_AQueue [code]: |
154 "Queue = AQueue []" |
153 "Queue = AQueue []" |
155 by (simp add: AQueue_def fun_eq_iff) |
154 by (simp add: AQueue_def fun_eq_iff) |
166 @{code_stmts empty enqueue dequeue Queue case_queue (SML)} |
165 @{code_stmts empty enqueue dequeue Queue case_queue (SML)} |
167 \<close> |
166 \<close> |
168 |
167 |
169 text \<open> |
168 text \<open> |
170 The same techniques can also be applied to types which are not |
169 The same techniques can also be applied to types which are not |
171 specified as datatypes, e.g.~type @{typ int} is originally specified |
170 specified as datatypes, e.g.~type \<^typ>\<open>int\<close> is originally specified |
172 as quotient type by means of @{command_def typedef}, but for code |
171 as quotient type by means of @{command_def typedef}, but for code |
173 generation constants allowing construction of binary numeral values |
172 generation constants allowing construction of binary numeral values |
174 are used as constructors for @{typ int}. |
173 are used as constructors for \<^typ>\<open>int\<close>. |
175 |
174 |
176 This approach however fails if the representation of a type demands |
175 This approach however fails if the representation of a type demands |
177 invariants; this issue is discussed in the next section. |
176 invariants; this issue is discussed in the next section. |
178 \<close> |
177 \<close> |
179 |
178 |
181 subsection \<open>Datatype refinement involving invariants \label{sec:invariant}\<close> |
180 subsection \<open>Datatype refinement involving invariants \label{sec:invariant}\<close> |
182 |
181 |
183 text \<open> |
182 text \<open> |
184 Datatype representation involving invariants require a dedicated |
183 Datatype representation involving invariants require a dedicated |
185 setup for the type and its primitive operations. As a running |
184 setup for the type and its primitive operations. As a running |
186 example, we implement a type @{typ "'a dlist"} of lists consisting |
185 example, we implement a type \<^typ>\<open>'a dlist\<close> of lists consisting |
187 of distinct elements. |
186 of distinct elements. |
188 |
187 |
189 The specification of @{typ "'a dlist"} itself can be found in theory |
188 The specification of \<^typ>\<open>'a dlist\<close> itself can be found in theory |
190 @{theory "HOL-Library.Dlist"}. |
189 \<^theory>\<open>HOL-Library.Dlist\<close>. |
191 |
190 |
192 The first step is to decide on which representation the abstract |
191 The first step is to decide on which representation the abstract |
193 type (in our example @{typ "'a dlist"}) should be implemented. |
192 type (in our example \<^typ>\<open>'a dlist\<close>) should be implemented. |
194 Here we choose @{typ "'a list"}. Then a conversion from the concrete |
193 Here we choose \<^typ>\<open>'a list\<close>. Then a conversion from the concrete |
195 type to the abstract type must be specified, here: |
194 type to the abstract type must be specified, here: |
196 \<close> |
195 \<close> |
197 |
196 |
198 text %quote \<open> |
197 text %quote \<open> |
199 @{term_type Dlist} |
198 \<^term_type>\<open>Dlist\<close> |
200 \<close> |
199 \<close> |
201 |
200 |
202 text \<open> |
201 text \<open> |
203 \noindent Next follows the specification of a suitable \emph{projection}, |
202 \noindent Next follows the specification of a suitable \emph{projection}, |
204 i.e.~a conversion from abstract to concrete type: |
203 i.e.~a conversion from abstract to concrete type: |
205 \<close> |
204 \<close> |
206 |
205 |
207 text %quote \<open> |
206 text %quote \<open> |
208 @{term_type list_of_dlist} |
207 \<^term_type>\<open>list_of_dlist\<close> |
209 \<close> |
208 \<close> |
210 |
209 |
211 text \<open> |
210 text \<open> |
212 \noindent This projection must be specified such that the following |
211 \noindent This projection must be specified such that the following |
213 \emph{abstract datatype certificate} can be proven: |
212 \emph{abstract datatype certificate} can be proven: |
217 "Dlist (list_of_dlist dxs) = dxs" |
216 "Dlist (list_of_dlist dxs) = dxs" |
218 by (fact Dlist_list_of_dlist) |
217 by (fact Dlist_list_of_dlist) |
219 |
218 |
220 text \<open> |
219 text \<open> |
221 \noindent Note that so far the invariant on representations |
220 \noindent Note that so far the invariant on representations |
222 (@{term_type distinct}) has never been mentioned explicitly: |
221 (\<^term_type>\<open>distinct\<close>) has never been mentioned explicitly: |
223 the invariant is only referred to implicitly: all values in |
222 the invariant is only referred to implicitly: all values in |
224 set @{term "{xs. list_of_dlist (Dlist xs) = xs}"} are invariant, |
223 set \<^term>\<open>{xs. list_of_dlist (Dlist xs) = xs}\<close> are invariant, |
225 and in our example this is exactly @{term "{xs. distinct xs}"}. |
224 and in our example this is exactly \<^term>\<open>{xs. distinct xs}\<close>. |
226 |
225 |
227 The primitive operations on @{typ "'a dlist"} are specified |
226 The primitive operations on \<^typ>\<open>'a dlist\<close> are specified |
228 indirectly using the projection @{const list_of_dlist}. For |
227 indirectly using the projection \<^const>\<open>list_of_dlist\<close>. For |
229 the empty \<open>dlist\<close>, @{const Dlist.empty}, we finally want |
228 the empty \<open>dlist\<close>, \<^const>\<open>Dlist.empty\<close>, we finally want |
230 the code equation |
229 the code equation |
231 \<close> |
230 \<close> |
232 |
231 |
233 text %quote \<open> |
232 text %quote \<open> |
234 @{term "Dlist.empty = Dlist []"} |
233 \<^term>\<open>Dlist.empty = Dlist []\<close> |
235 \<close> |
234 \<close> |
236 |
235 |
237 text \<open> |
236 text \<open> |
238 \noindent This we have to prove indirectly as follows: |
237 \noindent This we have to prove indirectly as follows: |
239 \<close> |
238 \<close> |
242 "list_of_dlist Dlist.empty = []" |
241 "list_of_dlist Dlist.empty = []" |
243 by (fact list_of_dlist_empty) |
242 by (fact list_of_dlist_empty) |
244 |
243 |
245 text \<open> |
244 text \<open> |
246 \noindent This equation logically encodes both the desired code |
245 \noindent This equation logically encodes both the desired code |
247 equation and that the expression @{const Dlist} is applied to obeys |
246 equation and that the expression \<^const>\<open>Dlist\<close> is applied to obeys |
248 the implicit invariant. Equations for insertion and removal are |
247 the implicit invariant. Equations for insertion and removal are |
249 similar: |
248 similar: |
250 \<close> |
249 \<close> |
251 |
250 |
252 lemma %quote [code]: |
251 lemma %quote [code]: |
268 text \<open> |
267 text \<open> |
269 See further @{cite "Haftmann-Kraus-Kuncar-Nipkow:2013:data_refinement"} |
268 See further @{cite "Haftmann-Kraus-Kuncar-Nipkow:2013:data_refinement"} |
270 for the meta theory of datatype refinement involving invariants. |
269 for the meta theory of datatype refinement involving invariants. |
271 |
270 |
272 Typical data structures implemented by representations involving |
271 Typical data structures implemented by representations involving |
273 invariants are available in the library, theory @{theory "HOL-Library.Mapping"} |
272 invariants are available in the library, theory \<^theory>\<open>HOL-Library.Mapping\<close> |
274 specifies key-value-mappings (type @{typ "('a, 'b) mapping"}); |
273 specifies key-value-mappings (type \<^typ>\<open>('a, 'b) mapping\<close>); |
275 these can be implemented by red-black-trees (theory @{theory "HOL-Library.RBT"}). |
274 these can be implemented by red-black-trees (theory \<^theory>\<open>HOL-Library.RBT\<close>). |
276 \<close> |
275 \<close> |
277 |
276 |
278 end |
277 end |