27 \end{tabular} |
27 \end{tabular} |
28 \end{quote} |
28 \end{quote} |
29 |
29 |
30 We also generally assume you are working with the logic HOL. The examples |
30 We also generally assume you are working with the logic HOL. The examples |
31 that will be given might need to be adapted if you work in a different logic. |
31 that will be given might need to be adapted if you work in a different logic. |
32 *} |
32 \<close> |
33 |
33 |
34 section {* Including ML-Code\label{sec:include} *} |
34 section \<open>Including ML-Code\label{sec:include}\<close> |
35 |
35 |
36 text {* |
36 text \<open> |
37 The easiest and quickest way to include code in a theory is by using the |
37 The easiest and quickest way to include code in a theory is by using the |
38 \isacommand{ML}-command. For example: |
38 \isacommand{ML}-command. For example: |
39 |
39 |
40 \begin{isabelle} |
40 \begin{isabelle} |
41 \begin{graybox} |
41 \begin{graybox} |
42 \isacommand{ML}~@{text "\<verbopen>"}\isanewline |
42 \isacommand{ML}~\<open>\<verbopen>\<close>\isanewline |
43 \hspace{5mm}@{ML "3 + 4"}\isanewline |
43 \hspace{5mm}@{ML "3 + 4"}\isanewline |
44 @{text "\<verbclose>"}\isanewline |
44 \<open>\<verbclose>\<close>\isanewline |
45 @{text "> 7"}\smallskip |
45 \<open>> 7\<close>\smallskip |
46 \end{graybox} |
46 \end{graybox} |
47 \end{isabelle} |
47 \end{isabelle} |
48 |
48 |
49 If you work with ProofGeneral then like normal Isabelle scripts |
49 If you work with ProofGeneral then like normal Isabelle scripts |
50 \isacommand{ML}-commands can be evaluated by using the advance and |
50 \isacommand{ML}-commands can be evaluated by using the advance and |
51 undo buttons of your Isabelle environment. If you work with the |
51 undo buttons of your Isabelle environment. If you work with the |
52 Jedit GUI, then you just have to hover the cursor over the code |
52 Jedit GUI, then you just have to hover the cursor over the code |
53 and you see the evaluated result in the ``Output'' window. |
53 and you see the evaluated result in the ``Output'' window. |
54 |
54 |
55 As mentioned in the Introduction, we will drop the \isacommand{ML}~@{text |
55 As mentioned in the Introduction, we will drop the \isacommand{ML}~\<open>\<verbopen> \<dots> \<verbclose>\<close> scaffolding whenever we show code. The lines |
56 "\<verbopen> \<dots> \<verbclose>"} scaffolding whenever we show code. The lines |
|
57 prefixed with @{text [quotes] ">"} are not part of the code, rather they |
56 prefixed with @{text [quotes] ">"} are not part of the code, rather they |
58 indicate what the response is when the code is evaluated. There are also |
57 indicate what the response is when the code is evaluated. There are also |
59 the commands \isacommand{ML\_val} and \isacommand{ML\_prf} for including |
58 the commands \isacommand{ML\_val} and \isacommand{ML\_prf} for including |
60 ML-code. The first evaluates the given code, but any effect on the theory, |
59 ML-code. The first evaluates the given code, but any effect on the theory, |
61 in which the code is embedded, is suppressed. The second needs to be used if |
60 in which the code is embedded, is suppressed. The second needs to be used if |
62 ML-code is defined inside a proof. For example |
61 ML-code is defined inside a proof. For example |
63 |
62 |
64 \begin{quote} |
63 \begin{quote} |
65 \begin{isabelle} |
64 \begin{isabelle} |
66 \isacommand{lemma}~@{text "test:"}\isanewline |
65 \isacommand{lemma}~\<open>test:\<close>\isanewline |
67 \isacommand{shows}~@{text [quotes] "True"}\isanewline |
66 \isacommand{shows}~@{text [quotes] "True"}\isanewline |
68 \isacommand{ML\_prf}~@{text "\<verbopen>"}~@{ML "writeln \"Trivial!\""}~@{text "\<verbclose>"}\isanewline |
67 \isacommand{ML\_prf}~\<open>\<verbopen>\<close>~@{ML "writeln \"Trivial!\""}~\<open>\<verbclose>\<close>\isanewline |
69 \isacommand{oops} |
68 \isacommand{oops} |
70 \end{isabelle} |
69 \end{isabelle} |
71 \end{quote} |
70 \end{quote} |
72 |
71 |
73 However, both commands will only play minor roles in this tutorial (we most of |
72 However, both commands will only play minor roles in this tutorial (we most of |
82 \begin{tabular}{@ {}l} |
81 \begin{tabular}{@ {}l} |
83 \isacommand{theory} First\_Steps\\ |
82 \isacommand{theory} First\_Steps\\ |
84 \isacommand{imports} Main\\ |
83 \isacommand{imports} Main\\ |
85 \isacommand{begin}\\ |
84 \isacommand{begin}\\ |
86 \ldots\\ |
85 \ldots\\ |
87 \isacommand{ML\_file}~@{text "\"file_to_be_included.ML\""}\\ |
86 \isacommand{ML\_file}~\<open>"file_to_be_included.ML"\<close>\\ |
88 \ldots |
87 \ldots |
89 \end{tabular} |
88 \end{tabular} |
90 \end{quote} |
89 \end{quote} |
91 *} |
90 \<close> |
92 |
91 |
93 section {* Printing and Debugging\label{sec:printing} *} |
92 section \<open>Printing and Debugging\label{sec:printing}\<close> |
94 |
93 |
95 text {* |
94 text \<open> |
96 During development you might find it necessary to inspect data in your |
95 During development you might find it necessary to inspect data in your |
97 code. This can be done in a ``quick-and-dirty'' fashion using the function |
96 code. This can be done in a ``quick-and-dirty'' fashion using the function |
98 @{ML_ind writeln in Output}. For example |
97 @{ML_ind writeln in Output}. For example |
99 |
98 |
100 @{ML_response_fake [display,gray] "writeln \"any string\"" "\"any string\""} |
99 @{ML_response_fake [display,gray] "writeln \"any string\"" "\"any string\""} |
101 |
100 |
102 will print out @{text [quotes] "any string"}. |
101 will print out @{text [quotes] "any string"}. |
103 This function expects a string as argument. If you develop under |
102 This function expects a string as argument. If you develop under |
104 PolyML, then there is a convenient, though again ``quick-and-dirty'', method |
103 PolyML, then there is a convenient, though again ``quick-and-dirty'', method |
105 for converting values into strings, namely the antiquotation |
104 for converting values into strings, namely the antiquotation |
106 @{text "@{make_string}"}: |
105 \<open>@{make_string}\<close>: |
107 |
106 |
108 @{ML_response_fake [display,gray] "writeln (@{make_string} 1)" "\"1\""} |
107 @{ML_response_fake [display,gray] "writeln (@{make_string} 1)" "\"1\""} |
109 |
108 |
110 However, @{text "@{make_string}"} only works if the type of what |
109 However, \<open>@{make_string}\<close> only works if the type of what |
111 is converted is monomorphic and not a function. |
110 is converted is monomorphic and not a function. |
112 |
111 |
113 You can print out error messages with the function @{ML_ind error in Library}; |
112 You can print out error messages with the function @{ML_ind error in Library}; |
114 for example: |
113 for example: |
115 |
114 |
116 @{ML_response_fake [display,gray] |
115 @{ML_response_fake [display,gray] |
117 "if 0 = 1 then true else (error \"foo\")" |
116 "if 0 = 1 then true else (error \"foo\")" |
118 "*** foo |
117 "*** foo |
119 ***"} |
118 ***"} |
120 |
119 |
121 This function raises the exception @{text ERROR}, which will then |
120 This function raises the exception \<open>ERROR\<close>, which will then |
122 be displayed by the infrastructure indicating that it is an error by |
121 be displayed by the infrastructure indicating that it is an error by |
123 painting the output red. Note that this exception is meant |
122 painting the output red. Note that this exception is meant |
124 for ``user-level'' error messages seen by the ``end-user''. |
123 for ``user-level'' error messages seen by the ``end-user''. |
125 For messages where you want to indicate a genuine program error |
124 For messages where you want to indicate a genuine program error |
126 use the exception @{text Fail}. |
125 use the exception \<open>Fail\<close>. |
127 |
126 |
128 Most often you want to inspect contents of Isabelle's basic data structures, |
127 Most often you want to inspect contents of Isabelle's basic data structures, |
129 namely @{ML_type term}, @{ML_type typ}, @{ML_type cterm}, @{ML_type ctyp} |
128 namely @{ML_type term}, @{ML_type typ}, @{ML_type cterm}, @{ML_type ctyp} |
130 and @{ML_type thm}. Isabelle provides elaborate pretty-printing functions, |
129 and @{ML_type thm}. Isabelle provides elaborate pretty-printing functions, |
131 which we will explain in more detail in Section \ref{sec:pretty}. For now |
130 which we will explain in more detail in Section \ref{sec:pretty}. For now |
132 we just use the functions @{ML_ind writeln in Pretty} from the structure |
131 we just use the functions @{ML_ind writeln in Pretty} from the structure |
133 @{ML_struct Pretty} and @{ML_ind pretty_term in Syntax} from the structure |
132 @{ML_struct Pretty} and @{ML_ind pretty_term in Syntax} from the structure |
134 @{ML_struct Syntax}. For more convenience, we bind them to the toplevel. |
133 @{ML_struct Syntax}. For more convenience, we bind them to the toplevel. |
135 *} |
134 \<close> |
136 |
135 |
137 ML %grayML{*val pretty_term = Syntax.pretty_term |
136 ML %grayML\<open>val pretty_term = Syntax.pretty_term |
138 val pwriteln = Pretty.writeln*} |
137 val pwriteln = Pretty.writeln\<close> |
139 |
138 |
140 text {* |
139 text \<open> |
141 They can be used as follows |
140 They can be used as follows |
142 |
141 |
143 @{ML_response_fake [display,gray] |
142 @{ML_response_fake [display,gray] |
144 "pwriteln (pretty_term @{context} @{term \"1::nat\"})" |
143 "pwriteln (pretty_term @{context} @{term \"1::nat\"})" |
145 "\"1\""} |
144 "\"1\""} |
146 |
145 |
147 If there is more than one term to be printed, you can use the |
146 If there is more than one term to be printed, you can use the |
148 function @{ML_ind commas in Pretty} and @{ML_ind block in Pretty} |
147 function @{ML_ind commas in Pretty} and @{ML_ind block in Pretty} |
149 to separate them. |
148 to separate them. |
150 *} |
149 \<close> |
151 |
150 |
152 ML %grayML{*fun pretty_terms ctxt trms = |
151 ML %grayML\<open>fun pretty_terms ctxt trms = |
153 Pretty.block (Pretty.commas (map (pretty_term ctxt) trms))*} |
152 Pretty.block (Pretty.commas (map (pretty_term ctxt) trms))\<close> |
154 |
153 |
155 text {* |
154 text \<open> |
156 To print out terms together with their typing information, |
155 To print out terms together with their typing information, |
157 set the configuration value |
156 set the configuration value |
158 @{ML_ind show_types in Syntax} to @{ML true}. |
157 @{ML_ind show_types in Syntax} to @{ML true}. |
159 *} |
158 \<close> |
160 |
159 |
161 ML %grayML{*val show_types_ctxt = Config.put show_types true @{context}*} |
160 ML %grayML\<open>val show_types_ctxt = Config.put show_types true @{context}\<close> |
162 |
161 |
163 text {* |
162 text \<open> |
164 Now by using this context @{ML pretty_term} prints out |
163 Now by using this context @{ML pretty_term} prints out |
165 |
164 |
166 @{ML_response_fake [display, gray] |
165 @{ML_response_fake [display, gray] |
167 "pwriteln (pretty_term show_types_ctxt @{term \"(1::nat, x)\"})" |
166 "pwriteln (pretty_term show_types_ctxt @{term \"(1::nat, x)\"})" |
168 "(1::nat, x::'a)"} |
167 "(1::nat, x::'a)"} |
169 |
168 |
170 where @{text 1} and @{text x} are displayed with their inferred types. |
169 where \<open>1\<close> and \<open>x\<close> are displayed with their inferred types. |
171 Other configuration values that influence |
170 Other configuration values that influence |
172 printing of terms include |
171 printing of terms include |
173 |
172 |
174 \begin{itemize} |
173 \begin{itemize} |
175 \item @{ML_ind show_brackets in Syntax} |
174 \item @{ML_ind show_brackets in Syntax} |
176 \item @{ML_ind show_sorts in Syntax} |
175 \item @{ML_ind show_sorts in Syntax} |
177 \item @{ML_ind eta_contract in Syntax} |
176 \item @{ML_ind eta_contract in Syntax} |
178 \end{itemize} |
177 \end{itemize} |
179 |
178 |
180 A @{ML_type cterm} can be printed with the following function. |
179 A @{ML_type cterm} can be printed with the following function. |
181 *} |
180 \<close> |
182 |
181 |
183 ML %grayML %grayML{*fun pretty_cterm ctxt ctrm = |
182 ML %grayML %grayML\<open>fun pretty_cterm ctxt ctrm = |
184 pretty_term ctxt (Thm.term_of ctrm)*} |
183 pretty_term ctxt (Thm.term_of ctrm)\<close> |
185 |
184 |
186 text {* |
185 text \<open> |
187 Here the function @{ML_ind term_of in Thm} extracts the @{ML_type |
186 Here the function @{ML_ind term_of in Thm} extracts the @{ML_type |
188 term} from a @{ML_type cterm}. More than one @{ML_type cterm}s can be |
187 term} from a @{ML_type cterm}. More than one @{ML_type cterm}s can be |
189 printed again with @{ML commas in Pretty}. |
188 printed again with @{ML commas in Pretty}. |
190 *} |
189 \<close> |
191 |
190 |
192 ML %grayML{*fun pretty_cterms ctxt ctrms = |
191 ML %grayML\<open>fun pretty_cterms ctxt ctrms = |
193 Pretty.block (Pretty.commas (map (pretty_cterm ctxt) ctrms))*} |
192 Pretty.block (Pretty.commas (map (pretty_cterm ctxt) ctrms))\<close> |
194 |
193 |
195 text {* |
194 text \<open> |
196 The easiest way to get the string of a theorem is to transform it |
195 The easiest way to get the string of a theorem is to transform it |
197 into a @{ML_type term} using the function @{ML_ind prop_of in Thm}. |
196 into a @{ML_type term} using the function @{ML_ind prop_of in Thm}. |
198 *} |
197 \<close> |
199 |
198 |
200 ML %grayML{*fun pretty_thm ctxt thm = |
199 ML %grayML\<open>fun pretty_thm ctxt thm = |
201 pretty_term ctxt (Thm.prop_of thm)*} |
200 pretty_term ctxt (Thm.prop_of thm)\<close> |
202 |
201 |
203 text {* |
202 text \<open> |
204 Theorems include schematic variables, such as @{text "?P"}, |
203 Theorems include schematic variables, such as \<open>?P\<close>, |
205 @{text "?Q"} and so on. They are instantiated by Isabelle when a theorem is applied. |
204 \<open>?Q\<close> and so on. They are instantiated by Isabelle when a theorem is applied. |
206 For example, the theorem |
205 For example, the theorem |
207 @{thm [source] conjI} shown below can be used for any (typable) |
206 @{thm [source] conjI} shown below can be used for any (typable) |
208 instantiation of @{text "?P"} and @{text "?Q"}. |
207 instantiation of \<open>?P\<close> and \<open>?Q\<close>. |
209 |
208 |
210 @{ML_response_fake [display, gray] |
209 @{ML_response_fake [display, gray] |
211 "pwriteln (pretty_thm @{context} @{thm conjI})" |
210 "pwriteln (pretty_thm @{context} @{thm conjI})" |
212 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
211 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
213 |
212 |
214 However, to improve the readability when printing theorems, we |
213 However, to improve the readability when printing theorems, we |
215 can switch off the question marks as follows: |
214 can switch off the question marks as follows: |
216 *} |
215 \<close> |
217 |
216 |
218 ML %grayML{*fun pretty_thm_no_vars ctxt thm = |
217 ML %grayML\<open>fun pretty_thm_no_vars ctxt thm = |
219 let |
218 let |
220 val ctxt' = Config.put show_question_marks false ctxt |
219 val ctxt' = Config.put show_question_marks false ctxt |
221 in |
220 in |
222 pretty_term ctxt' (Thm.prop_of thm) |
221 pretty_term ctxt' (Thm.prop_of thm) |
223 end*} |
222 end\<close> |
224 |
223 |
225 text {* |
224 text \<open> |
226 With this function, theorem @{thm [source] conjI} is now printed as follows: |
225 With this function, theorem @{thm [source] conjI} is now printed as follows: |
227 |
226 |
228 @{ML_response_fake [display, gray] |
227 @{ML_response_fake [display, gray] |
229 "pwriteln (pretty_thm_no_vars @{context} @{thm conjI})" |
228 "pwriteln (pretty_thm_no_vars @{context} @{thm conjI})" |
230 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
229 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
231 |
230 |
232 Again the functions @{ML commas} and @{ML block in Pretty} help |
231 Again the functions @{ML commas} and @{ML block in Pretty} help |
233 with printing more than one theorem. |
232 with printing more than one theorem. |
234 *} |
233 \<close> |
235 |
234 |
236 ML %grayML{*fun pretty_thms ctxt thms = |
235 ML %grayML\<open>fun pretty_thms ctxt thms = |
237 Pretty.block (Pretty.commas (map (pretty_thm ctxt) thms)) |
236 Pretty.block (Pretty.commas (map (pretty_thm ctxt) thms)) |
238 |
237 |
239 fun pretty_thms_no_vars ctxt thms = |
238 fun pretty_thms_no_vars ctxt thms = |
240 Pretty.block (Pretty.commas (map (pretty_thm_no_vars ctxt) thms))*} |
239 Pretty.block (Pretty.commas (map (pretty_thm_no_vars ctxt) thms))\<close> |
241 |
240 |
242 text {* |
241 text \<open> |
243 Printing functions for @{ML_type typ} are |
242 Printing functions for @{ML_type typ} are |
244 *} |
243 \<close> |
245 |
244 |
246 ML %grayML{*fun pretty_typ ctxt ty = Syntax.pretty_typ ctxt ty |
245 ML %grayML\<open>fun pretty_typ ctxt ty = Syntax.pretty_typ ctxt ty |
247 fun pretty_typs ctxt tys = |
246 fun pretty_typs ctxt tys = |
248 Pretty.block (Pretty.commas (map (pretty_typ ctxt) tys))*} |
247 Pretty.block (Pretty.commas (map (pretty_typ ctxt) tys))\<close> |
249 |
248 |
250 text {* |
249 text \<open> |
251 respectively @{ML_type ctyp} |
250 respectively @{ML_type ctyp} |
252 *} |
251 \<close> |
253 |
252 |
254 ML %grayML{*fun pretty_ctyp ctxt cty = pretty_typ ctxt (Thm.typ_of cty) |
253 ML %grayML\<open>fun pretty_ctyp ctxt cty = pretty_typ ctxt (Thm.typ_of cty) |
255 fun pretty_ctyps ctxt ctys = |
254 fun pretty_ctyps ctxt ctys = |
256 Pretty.block (Pretty.commas (map (pretty_ctyp ctxt) ctys))*} |
255 Pretty.block (Pretty.commas (map (pretty_ctyp ctxt) ctys))\<close> |
257 |
256 |
258 text {* |
257 text \<open> |
259 \begin{readmore} |
258 \begin{readmore} |
260 The simple conversion functions from Isabelle's main datatypes to |
259 The simple conversion functions from Isabelle's main datatypes to |
261 @{ML_type string}s are implemented in @{ML_file "Pure/Syntax/syntax.ML"}. |
260 @{ML_type string}s are implemented in @{ML_file "Pure/Syntax/syntax.ML"}. |
262 The configuration values that change the printing information are declared in |
261 The configuration values that change the printing information are declared in |
263 @{ML_file "Pure/Syntax/printer.ML"}. |
262 @{ML_file "Pure/Syntax/printer.ML"}. |
296 |
295 |
297 \begin{readmore} |
296 \begin{readmore} |
298 Most of the basic string functions of Isabelle are defined in |
297 Most of the basic string functions of Isabelle are defined in |
299 @{ML_file "Pure/library.ML"}. |
298 @{ML_file "Pure/library.ML"}. |
300 \end{readmore} |
299 \end{readmore} |
301 *} |
300 \<close> |
302 |
301 |
303 |
302 |
304 section {* Combinators\label{sec:combinators} *} |
303 section \<open>Combinators\label{sec:combinators}\<close> |
305 |
304 |
306 text {* |
305 text \<open> |
307 For beginners perhaps the most puzzling parts in the existing code of |
306 For beginners perhaps the most puzzling parts in the existing code of |
308 Isabelle are the combinators. At first they seem to greatly obstruct the |
307 Isabelle are the combinators. At first they seem to greatly obstruct the |
309 comprehension of code, but after getting familiar with them and handled with |
308 comprehension of code, but after getting familiar with them and handled with |
310 care, they actually ease the understanding and also the programming. |
309 care, they actually ease the understanding and also the programming. |
311 |
310 |
312 The simplest combinator is @{ML_ind I in Library}, which is just the |
311 The simplest combinator is @{ML_ind I in Library}, which is just the |
313 identity function defined as |
312 identity function defined as |
314 *} |
313 \<close> |
315 |
314 |
316 ML %grayML{*fun I x = x*} |
315 ML %grayML\<open>fun I x = x\<close> |
317 |
316 |
318 text {* |
317 text \<open> |
319 Another simple combinator is @{ML_ind K in Library}, defined as |
318 Another simple combinator is @{ML_ind K in Library}, defined as |
320 *} |
319 \<close> |
321 |
320 |
322 ML %grayML{*fun K x = fn _ => x*} |
321 ML %grayML\<open>fun K x = fn _ => x\<close> |
323 |
322 |
324 text {* |
323 text \<open> |
325 @{ML K} ``wraps'' a function around @{text "x"} that ignores its argument. As a |
324 @{ML K} ``wraps'' a function around \<open>x\<close> that ignores its argument. As a |
326 result, @{ML K} defines a constant function always returning @{text x}. |
325 result, @{ML K} defines a constant function always returning \<open>x\<close>. |
327 |
326 |
328 The next combinator is reverse application, @{ML_ind "|>" in Basics}, defined as: |
327 The next combinator is reverse application, @{ML_ind "|>" in Basics}, defined as: |
329 *} |
328 \<close> |
330 |
329 |
331 ML %grayML{*fun x |> f = f x*} |
330 ML %grayML\<open>fun x |> f = f x\<close> |
332 |
331 |
333 text {* While just syntactic sugar for the usual function application, |
332 text \<open>While just syntactic sugar for the usual function application, |
334 the purpose of this combinator is to implement functions in a |
333 the purpose of this combinator is to implement functions in a |
335 ``waterfall fashion''. Consider for example the function *} |
334 ``waterfall fashion''. Consider for example the function\<close> |
336 |
335 |
337 ML %linenosgray{*fun inc_by_five x = |
336 ML %linenosgray\<open>fun inc_by_five x = |
338 x |> (fn x => x + 1) |
337 x |> (fn x => x + 1) |
339 |> (fn x => (x, x)) |
338 |> (fn x => (x, x)) |
340 |> fst |
339 |> fst |
341 |> (fn x => x + 4)*} |
340 |> (fn x => x + 4)\<close> |
342 |
341 |
343 text {* |
342 text \<open> |
344 which increments its argument @{text x} by 5. It does this by first |
343 which increments its argument \<open>x\<close> by 5. It does this by first |
345 incrementing the argument by 1 (Line 2); then storing the result in a pair |
344 incrementing the argument by 1 (Line 2); then storing the result in a pair |
346 (Line 3); taking the first component of the pair (Line 4) and finally |
345 (Line 3); taking the first component of the pair (Line 4) and finally |
347 incrementing the first component by 4 (Line 5). This kind of cascading |
346 incrementing the first component by 4 (Line 5). This kind of cascading |
348 manipulations of values is quite common when dealing with theories. The |
347 manipulations of values is quite common when dealing with theories. The |
349 reverse application allows you to read what happens in a top-down |
348 reverse application allows you to read what happens in a top-down |
350 manner. This kind of coding should be familiar, if you have been exposed to |
349 manner. This kind of coding should be familiar, if you have been exposed to |
351 Haskell's {\it do}-notation. Writing the function @{ML inc_by_five} using |
350 Haskell's {\it do}-notation. Writing the function @{ML inc_by_five} using |
352 the reverse application is much clearer than writing |
351 the reverse application is much clearer than writing |
353 *} |
352 \<close> |
354 |
353 |
355 ML %grayML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*} |
354 ML %grayML\<open>fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4\<close> |
356 |
355 |
357 text {* or *} |
356 text \<open>or\<close> |
358 |
357 |
359 ML %grayML{*fun inc_by_five x = |
358 ML %grayML\<open>fun inc_by_five x = |
360 ((fn x => x + 4) o fst o (fn x => (x, x)) o (fn x => x + 1)) x*} |
359 ((fn x => x + 4) o fst o (fn x => (x, x)) o (fn x => x + 1)) x\<close> |
361 |
360 |
362 text {* and typographically more economical than *} |
361 text \<open>and typographically more economical than\<close> |
363 |
362 |
364 ML %grayML{*fun inc_by_five x = |
363 ML %grayML\<open>fun inc_by_five x = |
365 let val y1 = x + 1 |
364 let val y1 = x + 1 |
366 val y2 = (y1, y1) |
365 val y2 = (y1, y1) |
367 val y3 = fst y2 |
366 val y3 = fst y2 |
368 val y4 = y3 + 4 |
367 val y4 = y3 + 4 |
369 in y4 end*} |
368 in y4 end\<close> |
370 |
369 |
371 text {* |
370 text \<open> |
372 Another reasons to avoid the let-bindings in the code above: |
371 Another reasons to avoid the let-bindings in the code above: |
373 it is easy to get the intermediate values wrong and |
372 it is easy to get the intermediate values wrong and |
374 the resulting code is difficult to maintain. |
373 the resulting code is difficult to maintain. |
375 |
374 |
376 In Isabelle a ``real world'' example for a function written in |
375 In Isabelle a ``real world'' example for a function written in |
377 the waterfall fashion might be the following code: |
376 the waterfall fashion might be the following code: |
378 *} |
377 \<close> |
379 |
378 |
380 ML %linenosgray{*fun apply_fresh_args f ctxt = |
379 ML %linenosgray\<open>fun apply_fresh_args f ctxt = |
381 f |> fastype_of |
380 f |> fastype_of |
382 |> binder_types |
381 |> binder_types |
383 |> map (pair "z") |
382 |> map (pair "z") |
384 |> Variable.variant_frees ctxt [f] |
383 |> Variable.variant_frees ctxt [f] |
385 |> map Free |
384 |> map Free |
386 |> curry list_comb f *} |
385 |> curry list_comb f\<close> |
387 |
386 |
388 text {* |
387 text \<open> |
389 This function takes a term and a context as arguments. If the term is of function |
388 This function takes a term and a context as arguments. If the term is of function |
390 type, then @{ML "apply_fresh_args"} returns the term with distinct variables |
389 type, then @{ML "apply_fresh_args"} returns the term with distinct variables |
391 applied to it. For example, below three variables are applied to the term |
390 applied to it. For example, below three variables are applied to the term |
392 @{term [show_types] "P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool"}: |
391 @{term [show_types] "P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool"}: |
393 |
392 |
427 |> pretty_term ctxt |
426 |> pretty_term ctxt |
428 |> pwriteln |
427 |> pwriteln |
429 end" |
428 end" |
430 "za z zb"} |
429 "za z zb"} |
431 |
430 |
432 where the @{text "za"} is correctly avoided. |
431 where the \<open>za\<close> is correctly avoided. |
433 |
432 |
434 The combinator @{ML_ind "#>" in Basics} is the reverse function composition. |
433 The combinator @{ML_ind "#>" in Basics} is the reverse function composition. |
435 It can be used to define the following function |
434 It can be used to define the following function |
436 *} |
435 \<close> |
437 |
436 |
438 ML %grayML{*val inc_by_six = |
437 ML %grayML\<open>val inc_by_six = |
439 (fn x => x + 1) #> |
438 (fn x => x + 1) #> |
440 (fn x => x + 2) #> |
439 (fn x => x + 2) #> |
441 (fn x => x + 3)*} |
440 (fn x => x + 3)\<close> |
442 |
441 |
443 text {* |
442 text \<open> |
444 which is the function composed of first the increment-by-one function and |
443 which is the function composed of first the increment-by-one function and |
445 then increment-by-two, followed by increment-by-three. Again, the reverse |
444 then increment-by-two, followed by increment-by-three. Again, the reverse |
446 function composition allows you to read the code top-down. This combinator |
445 function composition allows you to read the code top-down. This combinator |
447 is often used for setup functions inside the |
446 is often used for setup functions inside the |
448 \isacommand{setup}- or \isacommand{local\_setup}-command. These functions |
447 \isacommand{setup}- or \isacommand{local\_setup}-command. These functions |
449 have to be of type @{ML_type "theory -> theory"}, respectively |
448 have to be of type @{ML_type "theory -> theory"}, respectively |
450 @{ML_type "local_theory -> local_theory"}. More than one such setup function |
449 @{ML_type "local_theory -> local_theory"}. More than one such setup function |
451 can be composed with @{ML "#>"}. Consider for example the following code, |
450 can be composed with @{ML "#>"}. Consider for example the following code, |
452 where we store the theorems @{thm [source] conjI}, @{thm [source] conjunct1} |
451 where we store the theorems @{thm [source] conjI}, @{thm [source] conjunct1} |
453 and @{thm [source] conjunct2} under alternative names. |
452 and @{thm [source] conjunct2} under alternative names. |
454 *} |
453 \<close> |
455 |
454 |
456 local_setup %graylinenos {* |
455 local_setup %graylinenos \<open> |
457 let |
456 let |
458 fun my_note name thm = Local_Theory.note ((name, []), [thm]) #> snd |
457 fun my_note name thm = Local_Theory.note ((name, []), [thm]) #> snd |
459 in |
458 in |
460 my_note @{binding "foo_conjI"} @{thm conjI} #> |
459 my_note @{binding "foo_conjI"} @{thm conjI} #> |
461 my_note @{binding "bar_conjunct1"} @{thm conjunct1} #> |
460 my_note @{binding "bar_conjunct1"} @{thm conjunct1} #> |
462 my_note @{binding "bar_conjunct2"} @{thm conjunct2} |
461 my_note @{binding "bar_conjunct2"} @{thm conjunct2} |
463 end *} |
462 end\<close> |
464 |
463 |
465 text {* |
464 text \<open> |
466 The function @{ML_text "my_note"} in line 3 is just a wrapper for the function |
465 The function @{ML_text "my_note"} in line 3 is just a wrapper for the function |
467 @{ML_ind note in Local_Theory} in the structure @{ML_struct Local_Theory}; |
466 @{ML_ind note in Local_Theory} in the structure @{ML_struct Local_Theory}; |
468 it stores a theorem under a name. |
467 it stores a theorem under a name. |
469 In lines 5 to 6 we call this function to give alternative names for the three |
468 In lines 5 to 6 we call this function to give alternative names for the three |
470 theorems. The point of @{ML "#>"} is that you can sequence such function calls. |
469 theorems. The point of @{ML "#>"} is that you can sequence such function calls. |
472 The remaining combinators we describe in this section add convenience for |
471 The remaining combinators we describe in this section add convenience for |
473 the ``waterfall method'' of writing functions. The combinator @{ML_ind tap |
472 the ``waterfall method'' of writing functions. The combinator @{ML_ind tap |
474 in Basics} allows you to get hold of an intermediate result (to do some |
473 in Basics} allows you to get hold of an intermediate result (to do some |
475 side-calculations or print out an intermediate result, for instance). The |
474 side-calculations or print out an intermediate result, for instance). The |
476 function |
475 function |
477 *} |
476 \<close> |
478 |
477 |
479 ML %linenosgray{*fun inc_by_three x = |
478 ML %linenosgray\<open>fun inc_by_three x = |
480 x |> (fn x => x + 1) |
479 x |> (fn x => x + 1) |
481 |> tap (fn x => pwriteln (Pretty.str (@{make_string} x))) |
480 |> tap (fn x => pwriteln (Pretty.str (@{make_string} x))) |
482 |> (fn x => x + 2)*} |
481 |> (fn x => x + 2)\<close> |
483 |
482 |
484 text {* |
483 text \<open> |
485 increments the argument first by @{text "1"} and then by @{text "2"}. In the |
484 increments the argument first by \<open>1\<close> and then by \<open>2\<close>. In the |
486 middle (Line 3), however, it uses @{ML tap} for printing the ``plus-one'' |
485 middle (Line 3), however, it uses @{ML tap} for printing the ``plus-one'' |
487 intermediate result. The function @{ML tap} can only be used for |
486 intermediate result. The function @{ML tap} can only be used for |
488 side-calculations, because any value that is computed cannot be merged back |
487 side-calculations, because any value that is computed cannot be merged back |
489 into the ``main waterfall''. To do this, you can use the next combinator. |
488 into the ``main waterfall''. To do this, you can use the next combinator. |
490 |
489 |
491 The combinator @{ML_ind "`" in Basics} (a backtick) is similar to @{ML tap}, |
490 The combinator @{ML_ind "`" in Basics} (a backtick) is similar to @{ML tap}, |
492 but applies a function to the value and returns the result together with the |
491 but applies a function to the value and returns the result together with the |
493 value (as a pair). It is defined as |
492 value (as a pair). It is defined as |
494 *} |
493 \<close> |
495 |
494 |
496 ML %grayML{*fun `f = fn x => (f x, x)*} |
495 ML %grayML\<open>fun `f = fn x => (f x, x)\<close> |
497 |
496 |
498 text {* |
497 text \<open> |
499 An example for this combinator is the function |
498 An example for this combinator is the function |
500 *} |
499 \<close> |
501 |
500 |
502 ML %grayML{*fun inc_as_pair x = |
501 ML %grayML\<open>fun inc_as_pair x = |
503 x |> `(fn x => x + 1) |
502 x |> `(fn x => x + 1) |
504 |> (fn (x, y) => (x, y + 1))*} |
503 |> (fn (x, y) => (x, y + 1))\<close> |
505 |
504 |
506 text {* |
505 text \<open> |
507 which takes @{text x} as argument, and then increments @{text x}, but also keeps |
506 which takes \<open>x\<close> as argument, and then increments \<open>x\<close>, but also keeps |
508 @{text x}. The intermediate result is therefore the pair @{ML "(x + 1, x)" |
507 \<open>x\<close>. The intermediate result is therefore the pair @{ML "(x + 1, x)" |
509 for x}. After that, the function increments the right-hand component of the |
508 for x}. After that, the function increments the right-hand component of the |
510 pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}. |
509 pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}. |
511 |
510 |
512 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
511 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
513 defined for functions manipulating pairs. The first applies the function to |
512 defined for functions manipulating pairs. The first applies the function to |
514 the first component of the pair, defined as |
513 the first component of the pair, defined as |
515 *} |
514 \<close> |
516 |
515 |
517 ML %grayML{*fun (x, y) |>> f = (f x, y)*} |
516 ML %grayML\<open>fun (x, y) |>> f = (f x, y)\<close> |
518 |
517 |
519 text {* |
518 text \<open> |
520 and the second combinator to the second component, defined as |
519 and the second combinator to the second component, defined as |
521 *} |
520 \<close> |
522 |
521 |
523 ML %grayML{*fun (x, y) ||> f = (x, f y)*} |
522 ML %grayML\<open>fun (x, y) ||> f = (x, f y)\<close> |
524 |
523 |
525 text {* |
524 text \<open> |
526 These two functions can, for example, be used to avoid explicit @{text "lets"} for |
525 These two functions can, for example, be used to avoid explicit \<open>lets\<close> for |
527 intermediate values in functions that return pairs. As an example, suppose you |
526 intermediate values in functions that return pairs. As an example, suppose you |
528 want to separate a list of integers into two lists according to a |
527 want to separate a list of integers into two lists according to a |
529 threshold. If the threshold is @{ML "5"}, the list @{ML "[1,6,2,5,3,4]"} |
528 threshold. If the threshold is @{ML "5"}, the list @{ML "[1,6,2,5,3,4]"} |
530 should be separated as @{ML "([1,2,3,4], [6,5])"}. Such a function can be |
529 should be separated as @{ML "([1,2,3,4], [6,5])"}. Such a function can be |
531 implemented as |
530 implemented as |
532 *} |
531 \<close> |
533 |
532 |
534 ML %grayML{*fun separate i [] = ([], []) |
533 ML %grayML\<open>fun separate i [] = ([], []) |
535 | separate i (x::xs) = |
534 | separate i (x::xs) = |
536 let |
535 let |
537 val (los, grs) = separate i xs |
536 val (los, grs) = separate i xs |
538 in |
537 in |
539 if i <= x then (los, x::grs) else (x::los, grs) |
538 if i <= x then (los, x::grs) else (x::los, grs) |
540 end*} |
539 end\<close> |
541 |
540 |
542 text {* |
541 text \<open> |
543 where the return value of the recursive call is bound explicitly to |
542 where the return value of the recursive call is bound explicitly to |
544 the pair @{ML "(los, grs)" for los grs}. However, this function |
543 the pair @{ML "(los, grs)" for los grs}. However, this function |
545 can be implemented more concisely as |
544 can be implemented more concisely as |
546 *} |
545 \<close> |
547 |
546 |
548 ML %grayML{*fun separate _ [] = ([], []) |
547 ML %grayML\<open>fun separate _ [] = ([], []) |
549 | separate i (x::xs) = |
548 | separate i (x::xs) = |
550 if i <= x |
549 if i <= x |
551 then separate i xs ||> cons x |
550 then separate i xs ||> cons x |
552 else separate i xs |>> cons x*} |
551 else separate i xs |>> cons x\<close> |
553 |
552 |
554 text {* |
553 text \<open> |
555 avoiding the explicit @{text "let"}. While in this example the gain in |
554 avoiding the explicit \<open>let\<close>. While in this example the gain in |
556 conciseness is only small, in more complicated situations the benefit of |
555 conciseness is only small, in more complicated situations the benefit of |
557 avoiding @{text "lets"} can be substantial. |
556 avoiding \<open>lets\<close> can be substantial. |
558 |
557 |
559 With the combinator @{ML_ind "|->" in Basics} you can re-combine the |
558 With the combinator @{ML_ind "|->" in Basics} you can re-combine the |
560 elements from a pair. This combinator is defined as |
559 elements from a pair. This combinator is defined as |
561 *} |
560 \<close> |
562 |
561 |
563 ML %grayML{*fun (x, y) |-> f = f x y*} |
562 ML %grayML\<open>fun (x, y) |-> f = f x y\<close> |
564 |
563 |
565 text {* |
564 text \<open> |
566 and can be used to write the following roundabout version |
565 and can be used to write the following roundabout version |
567 of the @{text double} function: |
566 of the \<open>double\<close> function: |
568 *} |
567 \<close> |
569 |
568 |
570 ML %grayML{*fun double x = |
569 ML %grayML\<open>fun double x = |
571 x |> (fn x => (x, x)) |
570 x |> (fn x => (x, x)) |
572 |-> (fn x => fn y => x + y)*} |
571 |-> (fn x => fn y => x + y)\<close> |
573 |
572 |
574 text {* |
573 text \<open> |
575 The combinator @{ML_ind ||>> in Basics} plays a central role whenever your |
574 The combinator @{ML_ind ||>> in Basics} plays a central role whenever your |
576 task is to update a theory and the update also produces a side-result (for |
575 task is to update a theory and the update also produces a side-result (for |
577 example a theorem). Functions for such tasks return a pair whose second |
576 example a theorem). Functions for such tasks return a pair whose second |
578 component is the theory and the fist component is the side-result. Using |
577 component is the theory and the fist component is the side-result. Using |
579 @{ML ||>>}, you can do conveniently the update and also |
578 @{ML ||>>}, you can do conveniently the update and also |
580 accumulate the side-results. Consider the following simple function. |
579 accumulate the side-results. Consider the following simple function. |
581 *} |
580 \<close> |
582 |
581 |
583 ML %linenosgray{*fun acc_incs x = |
582 ML %linenosgray\<open>fun acc_incs x = |
584 x |> (fn x => ("", x)) |
583 x |> (fn x => ("", x)) |
585 ||>> (fn x => (x, x + 1)) |
584 ||>> (fn x => (x, x + 1)) |
586 ||>> (fn x => (x, x + 1)) |
585 ||>> (fn x => (x, x + 1)) |
587 ||>> (fn x => (x, x + 1))*} |
586 ||>> (fn x => (x, x + 1))\<close> |
588 |
587 |
589 text {* |
588 text \<open> |
590 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
589 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
591 @{ML ||>>} operates on pairs). Each of the next three lines just increment |
590 @{ML ||>>} operates on pairs). Each of the next three lines just increment |
592 the value by one, but also nest the intermediate results to the left. For example |
591 the value by one, but also nest the intermediate results to the left. For example |
593 |
592 |
594 @{ML_response [display,gray] |
593 @{ML_response [display,gray] |
742 only in the text parts of Isabelle and their purpose is to print logical |
741 only in the text parts of Isabelle and their purpose is to print logical |
743 entities inside \LaTeX-documents. Document antiquotations are part of the |
742 entities inside \LaTeX-documents. Document antiquotations are part of the |
744 user level and therefore we are not interested in them in this Tutorial, |
743 user level and therefore we are not interested in them in this Tutorial, |
745 except in Appendix \ref{rec:docantiquotations} where we show how to |
744 except in Appendix \ref{rec:docantiquotations} where we show how to |
746 implement your own document antiquotations.} Syntactically antiquotations |
745 implement your own document antiquotations.} Syntactically antiquotations |
747 are indicated by the @{ML_text @}-sign followed by text wrapped in @{text |
746 are indicated by the @{ML_text @}-sign followed by text wrapped in \<open>{\<dots>}\<close>. For example, one can print out the name of the current theory with |
748 "{\<dots>}"}. For example, one can print out the name of the current theory with |
|
749 the code |
747 the code |
750 |
748 |
751 @{ML_response [display,gray] "Context.theory_name @{theory}" "\"First_Steps\""} |
749 @{ML_response [display,gray] "Context.theory_name @{theory}" "\"First_Steps\""} |
752 |
750 |
753 where @{text "@{theory}"} is an antiquotation that is substituted with the |
751 where \<open>@{theory}\<close> is an antiquotation that is substituted with the |
754 current theory (remember that we assumed we are inside the theory |
752 current theory (remember that we assumed we are inside the theory |
755 @{text First_Steps}). The name of this theory can be extracted using |
753 \<open>First_Steps\<close>). The name of this theory can be extracted using |
756 the function @{ML_ind theory_name in Context}. |
754 the function @{ML_ind theory_name in Context}. |
757 |
755 |
758 Note, however, that antiquotations are statically linked, that is their value is |
756 Note, however, that antiquotations are statically linked, that is their value is |
759 determined at ``compile-time'', not at ``run-time''. For example the function |
757 determined at ``compile-time'', not at ``run-time''. For example the function |
760 *} |
758 \<close> |
761 |
759 |
762 ML %grayML{*fun not_current_thyname () = Context.theory_name @{theory} *} |
760 ML %grayML\<open>fun not_current_thyname () = Context.theory_name @{theory}\<close> |
763 |
761 |
764 text {* |
762 text \<open> |
765 does \emph{not} return the name of the current theory, if it is run in a |
763 does \emph{not} return the name of the current theory, if it is run in a |
766 different theory. Instead, the code above defines the constant function |
764 different theory. Instead, the code above defines the constant function |
767 that always returns the string @{text [quotes] "First_Steps"}, no matter where the |
765 that always returns the string @{text [quotes] "First_Steps"}, no matter where the |
768 function is called. Operationally speaking, the antiquotation @{text "@{theory}"} is |
766 function is called. Operationally speaking, the antiquotation \<open>@{theory}\<close> is |
769 \emph{not} replaced with code that will look up the current theory in |
767 \emph{not} replaced with code that will look up the current theory in |
770 some data structure and return it. Instead, it is literally |
768 some data structure and return it. Instead, it is literally |
771 replaced with the value representing the theory. |
769 replaced with the value representing the theory. |
772 |
770 |
773 Another important antiquotation is @{text "@{context}"}. (What the |
771 Another important antiquotation is \<open>@{context}\<close>. (What the |
774 difference between a theory and a context is will be described in Chapter |
772 difference between a theory and a context is will be described in Chapter |
775 \ref{chp:advanced}.) A context is for example needed to use the |
773 \ref{chp:advanced}.) A context is for example needed to use the |
776 function @{ML print_abbrevs in Proof_Context} that list of all currently |
774 function @{ML print_abbrevs in Proof_Context} that list of all currently |
777 defined abbreviations. For example |
775 defined abbreviations. For example |
778 |
776 |
809 The point of these antiquotations is that referring to theorems in this way |
807 The point of these antiquotations is that referring to theorems in this way |
810 makes your code independent from what theorems the user might have stored |
808 makes your code independent from what theorems the user might have stored |
811 under this name (this becomes especially important when you deal with |
809 under this name (this becomes especially important when you deal with |
812 theorem lists; see Section \ref{sec:storing}). |
810 theorem lists; see Section \ref{sec:storing}). |
813 |
811 |
814 It is also possible to prove lemmas with the antiquotation @{text "@{lemma \<dots> by \<dots>}"} |
812 It is also possible to prove lemmas with the antiquotation \<open>@{lemma \<dots> by \<dots>}\<close> |
815 whose first argument is a statement (possibly many of them separated by @{text "and"}) |
813 whose first argument is a statement (possibly many of them separated by \<open>and\<close>) |
816 and the second is a proof. For example |
814 and the second is a proof. For example |
817 *} |
815 \<close> |
818 |
816 |
819 ML %grayML{*val foo_thms = @{lemma "True" and "False \<Longrightarrow> P" by simp_all} *} |
817 ML %grayML\<open>val foo_thms = @{lemma "True" and "False \<Longrightarrow> P" by simp_all}\<close> |
820 |
818 |
821 text {* |
819 text \<open> |
822 The result can be printed out as follows. |
820 The result can be printed out as follows. |
823 |
821 |
824 @{ML_response_fake [gray,display] |
822 @{ML_response_fake [gray,display] |
825 "foo_thms |> pretty_thms_no_vars @{context} |
823 "foo_thms |> pretty_thms_no_vars @{context} |
826 |> pwriteln" |
824 |> pwriteln" |
827 "True, False \<Longrightarrow> P"} |
825 "True, False \<Longrightarrow> P"} |
828 |
826 |
829 You can also refer to the current simpset via an antiquotation. To illustrate |
827 You can also refer to the current simpset via an antiquotation. To illustrate |
830 this we implement the function that extracts the theorem names stored in a |
828 this we implement the function that extracts the theorem names stored in a |
831 simpset. |
829 simpset. |
832 *} |
830 \<close> |
833 |
831 |
834 ML %grayML{*fun get_thm_names_from_ss ctxt = |
832 ML %grayML\<open>fun get_thm_names_from_ss ctxt = |
835 let |
833 let |
836 val simpset = Raw_Simplifier.simpset_of ctxt |
834 val simpset = Raw_Simplifier.simpset_of ctxt |
837 val {simps,...} = Raw_Simplifier.dest_ss simpset |
835 val {simps,...} = Raw_Simplifier.dest_ss simpset |
838 in |
836 in |
839 map #1 simps |
837 map #1 simps |
840 end*} |
838 end\<close> |
841 |
839 |
842 text {* |
840 text \<open> |
843 The function @{ML_ind dest_ss in Raw_Simplifier} returns a record containing all |
841 The function @{ML_ind dest_ss in Raw_Simplifier} returns a record containing all |
844 information stored in the simpset, but here we are only interested in the names of the |
842 information stored in the simpset, but here we are only interested in the names of the |
845 simp-rules. Now you can feed in the current simpset into this function. |
843 simp-rules. Now you can feed in the current simpset into this function. |
846 The current simpset can be referred to using @{ML_ind simpset_of in Raw_Simplifier}. |
844 The current simpset can be referred to using @{ML_ind simpset_of in Raw_Simplifier}. |
847 |
845 |
854 code. |
852 code. |
855 |
853 |
856 It is also possible to define your own antiquotations. But you should |
854 It is also possible to define your own antiquotations. But you should |
857 exercise care when introducing new ones, as they can also make your code |
855 exercise care when introducing new ones, as they can also make your code |
858 difficult to read. In the next chapter we describe how to construct |
856 difficult to read. In the next chapter we describe how to construct |
859 terms with the (built-in) antiquotation @{text "@{term \<dots>}"}. A restriction |
857 terms with the (built-in) antiquotation \<open>@{term \<dots>}\<close>. A restriction |
860 of this antiquotation is that it does not allow you to use schematic |
858 of this antiquotation is that it does not allow you to use schematic |
861 variables in terms. If you want to have an antiquotation that does not have |
859 variables in terms. If you want to have an antiquotation that does not have |
862 this restriction, you can implement your own using the function @{ML_ind |
860 this restriction, you can implement your own using the function @{ML_ind |
863 inline in ML_Antiquotation} from the structure @{ML_struct ML_Antiquotation}. The code |
861 inline in ML_Antiquotation} from the structure @{ML_struct ML_Antiquotation}. The code |
864 for the antiquotation @{text "term_pat"} is as follows. |
862 for the antiquotation \<open>term_pat\<close> is as follows. |
865 *} |
863 \<close> |
866 |
864 |
867 ML %linenosgray{*val term_pat_setup = |
865 ML %linenosgray\<open>val term_pat_setup = |
868 let |
866 let |
869 val parser = Args.context -- Scan.lift Args.embedded_inner_syntax |
867 val parser = Args.context -- Scan.lift Args.embedded_inner_syntax |
870 |
868 |
871 fun term_pat (ctxt, str) = |
869 fun term_pat (ctxt, str) = |
872 str |> Proof_Context.read_term_pattern ctxt |
870 str |> Proof_Context.read_term_pattern ctxt |
873 |> ML_Syntax.print_term |
871 |> ML_Syntax.print_term |
874 |> ML_Syntax.atomic |
872 |> ML_Syntax.atomic |
875 in |
873 in |
876 ML_Antiquotation.inline @{binding "term_pat"} (parser >> term_pat) |
874 ML_Antiquotation.inline @{binding "term_pat"} (parser >> term_pat) |
877 end*} |
875 end\<close> |
878 |
876 |
879 text {* |
877 text \<open> |
880 To use it you also have to install it using \isacommand{setup} like so |
878 To use it you also have to install it using \isacommand{setup} like so |
881 *} |
879 \<close> |
882 |
880 |
883 setup %gray {* term_pat_setup *} |
881 setup %gray \<open>term_pat_setup\<close> |
884 |
882 |
885 text {* |
883 text \<open> |
886 The parser in Line 2 provides us with a context and a string; this string is |
884 The parser in Line 2 provides us with a context and a string; this string is |
887 transformed into a term using the function @{ML_ind read_term_pattern in |
885 transformed into a term using the function @{ML_ind read_term_pattern in |
888 Proof_Context} (Line 5); the next two lines transform the term into a string |
886 Proof_Context} (Line 5); the next two lines transform the term into a string |
889 so that the ML-system can understand it. (All these functions will be explained |
887 so that the ML-system can understand it. (All these functions will be explained |
890 in more detail in later sections.) An example for this antiquotation is: |
888 in more detail in later sections.) An example for this antiquotation is: |
891 |
889 |
892 @{ML_response_fake [display,gray] |
890 @{ML_response_fake [display,gray] |
893 "@{term_pat \"Suc (?x::nat)\"}" |
891 "@{term_pat \"Suc (?x::nat)\"}" |
894 "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"} |
892 "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"} |
895 |
893 |
896 which shows the internal representation of the term @{text "Suc ?x"}. Similarly |
894 which shows the internal representation of the term \<open>Suc ?x\<close>. Similarly |
897 we can write an antiquotation for type patterns. Its code is |
895 we can write an antiquotation for type patterns. Its code is |
898 *} |
896 \<close> |
899 |
897 |
900 ML %grayML{*val type_pat_setup = |
898 ML %grayML\<open>val type_pat_setup = |
901 let |
899 let |
902 val parser = Args.context -- Scan.lift Args.embedded_inner_syntax |
900 val parser = Args.context -- Scan.lift Args.embedded_inner_syntax |
903 |
901 |
904 fun typ_pat (ctxt, str) = |
902 fun typ_pat (ctxt, str) = |
905 let |
903 let |
1214 |
1212 |
1215 Move elsewhere |
1213 Move elsewhere |
1216 |
1214 |
1217 For convenience there is an abstract layer, namely the type @{ML_type Context.generic}, |
1215 For convenience there is an abstract layer, namely the type @{ML_type Context.generic}, |
1218 for treating theories and proof contexts more uniformly. This type is defined as follows |
1216 for treating theories and proof contexts more uniformly. This type is defined as follows |
1219 *} |
1217 \<close> |
1220 |
1218 |
1221 ML_val %grayML{*datatype generic = |
1219 ML_val %grayML\<open>datatype generic = |
1222 Theory of theory |
1220 Theory of theory |
1223 | Proof of proof*} |
1221 | Proof of proof\<close> |
1224 |
1222 |
1225 text {* |
1223 text \<open> |
1226 \footnote{\bf FIXME: say more about generic contexts.} |
1224 \footnote{\bf FIXME: say more about generic contexts.} |
1227 |
1225 |
1228 There are two special instances of the data storage mechanism described |
1226 There are two special instances of the data storage mechanism described |
1229 above. The first instance implements named theorem lists using the functor |
1227 above. The first instance implements named theorem lists using the functor |
1230 @{ML_funct_ind Named_Thms}. This is because storing theorems in a list |
1228 @{ML_funct_ind Named_Thms}. This is because storing theorems in a list |
1231 is such a common task. To obtain a named theorem list, you just declare |
1229 is such a common task. To obtain a named theorem list, you just declare |
1232 *} |
1230 \<close> |
1233 |
1231 |
1234 ML %grayML{*structure FooRules = Named_Thms |
1232 ML %grayML\<open>structure FooRules = Named_Thms |
1235 (val name = @{binding "foo"} |
1233 (val name = @{binding "foo"} |
1236 val description = "Theorems for foo") *} |
1234 val description = "Theorems for foo")\<close> |
1237 |
1235 |
1238 text {* |
1236 text \<open> |
1239 and set up the @{ML_struct FooRules} with the command |
1237 and set up the @{ML_struct FooRules} with the command |
1240 *} |
1238 \<close> |
1241 |
1239 |
1242 setup %gray {* FooRules.setup *} |
1240 setup %gray \<open>FooRules.setup\<close> |
1243 |
1241 |
1244 text {* |
1242 text \<open> |
1245 This code declares a data container where the theorems are stored, |
1243 This code declares a data container where the theorems are stored, |
1246 an attribute @{text foo} (with the @{text add} and @{text del} options |
1244 an attribute \<open>foo\<close> (with the \<open>add\<close> and \<open>del\<close> options |
1247 for adding and deleting theorems) and an internal ML-interface for retrieving and |
1245 for adding and deleting theorems) and an internal ML-interface for retrieving and |
1248 modifying the theorems. |
1246 modifying the theorems. |
1249 Furthermore, the theorems are made available on the user-level under the name |
1247 Furthermore, the theorems are made available on the user-level under the name |
1250 @{text foo}. For example you can declare three lemmas to be a member of the |
1248 \<open>foo\<close>. For example you can declare three lemmas to be a member of the |
1251 theorem list @{text foo} by: |
1249 theorem list \<open>foo\<close> by: |
1252 *} |
1250 \<close> |
1253 |
1251 |
1254 lemma rule1[foo]: "A" sorry |
1252 lemma rule1[foo]: "A" sorry |
1255 lemma rule2[foo]: "B" sorry |
1253 lemma rule2[foo]: "B" sorry |
1256 lemma rule3[foo]: "C" sorry |
1254 lemma rule3[foo]: "C" sorry |
1257 |
1255 |
1258 text {* and undeclare the first one by: *} |
1256 text \<open>and undeclare the first one by:\<close> |
1259 |
1257 |
1260 declare rule1[foo del] |
1258 declare rule1[foo del] |
1261 |
1259 |
1262 text {* You can query the remaining ones with: |
1260 text \<open>You can query the remaining ones with: |
1263 |
1261 |
1264 \begin{isabelle} |
1262 \begin{isabelle} |
1265 \isacommand{thm}~@{text "foo"}\\ |
1263 \isacommand{thm}~\<open>foo\<close>\\ |
1266 @{text "> ?C"}\\ |
1264 \<open>> ?C\<close>\\ |
1267 @{text "> ?B"} |
1265 \<open>> ?B\<close> |
1268 \end{isabelle} |
1266 \end{isabelle} |
1269 |
1267 |
1270 On the ML-level, we can add theorems to the list with @{ML FooRules.add_thm}: |
1268 On the ML-level, we can add theorems to the list with @{ML FooRules.add_thm}: |
1271 *} |
1269 \<close> |
1272 |
1270 |
1273 setup %gray {* Context.theory_map (FooRules.add_thm @{thm TrueI}) *} |
1271 setup %gray \<open>Context.theory_map (FooRules.add_thm @{thm TrueI})\<close> |
1274 |
1272 |
1275 text {* |
1273 text \<open> |
1276 The rules in the list can be retrieved using the function |
1274 The rules in the list can be retrieved using the function |
1277 @{ML FooRules.get}: |
1275 @{ML FooRules.get}: |
1278 |
1276 |
1279 @{ML_response_fake [display,gray] |
1277 @{ML_response_fake [display,gray] |
1280 "FooRules.get @{context}" |
1278 "FooRules.get @{context}" |