62 |
62 |
63 text {* |
63 text {* |
64 then Isabelle's undo operation has no effect on the definition of |
64 then Isabelle's undo operation has no effect on the definition of |
65 @{ML "foo"}. |
65 @{ML "foo"}. |
66 |
66 |
67 During coding you might find it necessary to quickly inspect some data |
67 During developments you might find it necessary to quickly inspect some data |
68 in your code. This can be done in a ``quick-and-dirty'' fashion using |
68 in your code. This can be done in a ``quick-and-dirty'' fashion using |
69 @{ML "warning"}. For example |
69 the function @{ML "warning"}. For example |
70 *} |
70 *} |
71 |
71 |
72 ML {* |
72 ML {* |
73 val _ = warning "any string" |
73 val _ = warning "any string" |
74 *} |
74 *} |
128 *} |
128 *} |
129 |
129 |
130 section {* Terms *} |
130 section {* Terms *} |
131 |
131 |
132 text {* |
132 text {* |
133 Terms of Isabelle can be constructed on the ML-level using the @{text "@{term \<dots>}"} |
133 One way to construct terms of Isabelle on the ML-level is by using the antiquotation |
134 antiquotation: |
134 @{text "@{term \<dots>}"}: |
135 *} |
135 *} |
136 |
136 |
137 ML {* @{term "(a::nat) + b = c"} *} |
137 ML {* @{term "(a::nat) + b = c"} *} |
138 |
138 |
139 text {* |
139 text {* |
140 This will show the term @{term "(a::nat) + b = c"}, but printed out using the internal |
140 This will show the term @{term "(a::nat) + b = c"}, but printed out using the internal |
141 representation of this term. This internal represenation is just a |
141 representation of this term. This internal represenation corresponds to the |
142 datatype defined in @{ML_file "Pure/term.ML"}. |
142 datatype defined in @{ML_file "Pure/term.ML"}. |
143 |
143 |
144 The internal representation of terms uses the usual deBruin indices mechanism: bound |
144 The internal representation of terms uses the usual de-Bruijn indices mechanism where bound |
145 variables are represented by the constructor @{ML Bound} whose argument refers to |
145 variables are represented by the constructor @{ML Bound}. The index in @{ML Bound} refers to |
146 the number of Abstractions (@{ML Abs}) we have to skip until we hit the @{ML Abs} that |
146 the number of Abstractions (@{ML Abs}) we have to skip until we hit the @{ML Abs} that |
147 binds the corresponding variable. However, the names of bound variables are |
147 binds the corresponding variable. However, the names of bound variables are |
148 kept at abstractions for printing purposes, and so should be treated just as comments. |
148 kept at abstractions for printing purposes, and so should be treated only as comments. |
149 See \ichcite{ch:logic} for more details. |
|
150 |
|
151 (FIXME: Alex why is the reference bolow given. It somehow does not read |
|
152 with what is written above.) |
|
153 |
149 |
154 \begin{readmore} |
150 \begin{readmore} |
155 Terms are described in detail in \ichcite{ch:logic}. Their |
151 Terms are described in detail in \ichcite{ch:logic}. Their |
156 definition and many useful operations can be found in @{ML_file "Pure/term.ML"}. |
152 definition and many useful operations can be found in @{ML_file "Pure/term.ML"}. |
157 \end{readmore} |
153 \end{readmore} |
172 |
168 |
173 Hint: The third term is already quite big, and the pretty printer |
169 Hint: The third term is already quite big, and the pretty printer |
174 may omit parts of it by default. If you want to see all of it, you |
170 may omit parts of it by default. If you want to see all of it, you |
175 can use @{ML "print_depth 50"} to set the limit to a value high enough. |
171 can use @{ML "print_depth 50"} to set the limit to a value high enough. |
176 \end{exercise} |
172 \end{exercise} |
177 |
|
178 \begin{exercise} |
|
179 Write a function @{ML_text "rev_sum : term -> term"} that takes a |
|
180 term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} |
|
181 and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. |
|
182 Note that @{text "+"} associates to the left. |
|
183 Try your function on some examples, and see if the result typechecks. |
|
184 \end{exercise} |
|
185 *} |
|
186 |
|
187 text {* FIXME: check possible solution *} |
|
188 |
|
189 ML {* |
|
190 exception FORM_ERROR |
|
191 |
|
192 fun rev_sum term = |
|
193 case term of |
|
194 @{term "op +"} $ (Free (x,t1)) $ (Free (y,t2)) => |
|
195 @{term "op +"} $ (Free (y,t2)) $ (Free (x,t1)) |
|
196 | @{term "op +"} $ left $ (Free (x,t)) => |
|
197 @{term "op +"} $ (Free (x,t)) $ (rev_sum left) |
|
198 | _ => raise FORM_ERROR |
|
199 *} |
|
200 |
|
201 |
|
202 text {* |
|
203 \begin{exercise} |
|
204 Write a function which takes two terms representing natural numbers |
|
205 in unary (like @{term "Suc (Suc (Suc 0))"}), and produce the unary |
|
206 number representing their sum. |
|
207 \end{exercise} |
|
208 |
|
209 \begin{exercise} |
|
210 Look at the functions defined in @{ML_file "Pure/logic.ML"} and |
|
211 @{ML_file "HOL/hologic.ML"} and see if they can make your life |
|
212 easier. |
|
213 \end{exercise} |
|
214 |
|
215 (FIXME what is coming next should fit with the main flow) |
|
216 *} |
173 *} |
217 |
174 |
218 ML {* |
175 ML {* |
219 @{const_name plus} |
176 @{const_name plus} |
220 *} |
177 *} |
237 |
194 |
238 ML {* @{prop "True"} *} |
195 ML {* @{prop "True"} *} |
239 |
196 |
240 |
197 |
241 |
198 |
|
199 section {* Possible Section on Construting Explicitly Terms *} |
|
200 |
|
201 text {* |
|
202 |
|
203 There is a disadvantage of using the @{text "@{term \<dots>}"} antiquotation |
|
204 directly in order to construct terms. |
|
205 *} |
|
206 |
|
207 ML {* |
|
208 |
|
209 val nat = HOLogic.natT |
|
210 val x = Free ("x", nat) |
|
211 val t = Free ("t", nat) |
|
212 val P = Free ("P", nat --> HOLogic.boolT) |
|
213 val Q = Free ("Q", nat --> HOLogic.boolT) |
|
214 |
|
215 val A1 = Logic.all x |
|
216 (Logic.mk_implies (HOLogic.mk_Trueprop (P $ x), |
|
217 HOLogic.mk_Trueprop (Q $ x))) |
|
218 |
|
219 |
|
220 val A2 = HOLogic.mk_Trueprop (P $ t) |
|
221 |
|
222 *} |
|
223 |
|
224 text {* |
|
225 |
|
226 \begin{exercise} |
|
227 Write a function @{ML_text "rev_sum : term -> term"} that takes a |
|
228 term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "i"} might be zero) |
|
229 and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume |
|
230 the @{text "t\<^isub>i"} can be arbitrary expressions and also note that @{text "+"} |
|
231 associates to the left. Try your function on some examples, and see if |
|
232 the result typechecks. (FIXME: clash with the type-checking section later) |
|
233 \end{exercise} |
|
234 *} |
|
235 |
|
236 ML {* |
|
237 fun rev_sum t = |
|
238 let |
|
239 fun dest_sum (Const (@{const_name plus}, _) $ u $ u') = |
|
240 u' :: dest_sum u |
|
241 | dest_sum u = [u] |
|
242 in |
|
243 foldl1 (HOLogic.mk_binop @{const_name plus}) (dest_sum t) |
|
244 end; |
|
245 *} |
|
246 |
|
247 text {* |
|
248 \begin{exercise} |
|
249 Write a function which takes two terms representing natural numbers |
|
250 in unary (like @{term "Suc (Suc (Suc 0))"}), and produce the unary |
|
251 number representing their sum. |
|
252 \end{exercise} |
|
253 |
|
254 *} |
|
255 |
|
256 ML {* |
|
257 fun make_sum t1 t2 = |
|
258 HOLogic.mk_nat (HOLogic.dest_nat t1 + HOLogic.dest_nat t2) |
|
259 *} |
|
260 |
|
261 |
|
262 text {* |
|
263 \begin{exercise} |
|
264 Look at the functions defined in @{ML_file "Pure/logic.ML"} and |
|
265 @{ML_file "HOL/hologic.ML"} and see if they can make your life |
|
266 easier. |
|
267 \end{exercise} |
|
268 *} |
|
269 |
242 |
270 |
243 section {* Type checking *} |
271 section {* Type checking *} |
244 |
272 |
245 text {* |
273 text {* |
246 We can freely construct and manipulate terms, since they are just |
274 We can freely construct and manipulate terms, since they are just |
286 can be proved in ML like |
314 can be proved in ML like |
287 this\footnote{Note that @{text "|>"} is just reverse |
315 this\footnote{Note that @{text "|>"} is just reverse |
288 application. This combinator, and several variants are defined in |
316 application. This combinator, and several variants are defined in |
289 @{ML_file "Pure/General/basics.ML"}}: |
317 @{ML_file "Pure/General/basics.ML"}}: |
290 |
318 |
291 |
319 *} |
292 (FIXME: Alex why did you not use antiquotations for this?) |
320 |
293 *} |
321 |
294 |
|
295 ML {* |
|
296 let |
|
297 val thy = @{theory} |
|
298 val nat = HOLogic.natT |
|
299 val x = Free ("x", nat) |
|
300 val t = Free ("t", nat) |
|
301 val P = Free ("P", nat --> HOLogic.boolT) |
|
302 val Q = Free ("Q", nat --> HOLogic.boolT) |
|
303 |
|
304 val A1 = Logic.all x |
|
305 (Logic.mk_implies (HOLogic.mk_Trueprop (P $ x), |
|
306 HOLogic.mk_Trueprop (Q $ x))) |
|
307 |> cterm_of thy |
|
308 |
|
309 val A2 = HOLogic.mk_Trueprop (P $ t) |
|
310 |> cterm_of thy |
|
311 |
|
312 val Pt_implies_Qt = |
|
313 assume A1 |
|
314 |> forall_elim (cterm_of thy t) |
|
315 |
|
316 val Qt = implies_elim Pt_implies_Qt (assume A2) |
|
317 in |
|
318 Qt |
|
319 |> implies_intr A2 |
|
320 |> implies_intr A1 |
|
321 end |
|
322 *} |
|
323 |
322 |
324 ML {* |
323 ML {* |
325 |
324 |
326 let |
325 let |
327 val thy = @{theory} |
326 val thy = @{theory} |
407 |
406 |
408 text {* |
407 text {* |
409 Tactics that affect only a certain subgoal, take a subgoal number as |
408 Tactics that affect only a certain subgoal, take a subgoal number as |
410 an integer parameter. Here we always work on the first subgoal, |
409 an integer parameter. Here we always work on the first subgoal, |
411 following exactly the @{text "apply"} script. |
410 following exactly the @{text "apply"} script. |
|
411 |
|
412 (Fixme: would it make sense to explain THEN' here) |
|
413 |
412 *} |
414 *} |
413 |
415 |
414 |
416 |
415 section {* Case Study: Relation Composition *} |
417 section {* Case Study: Relation Composition *} |
416 |
418 |