230 %Fail, although there is some special treatment when Toplevel.debug is |
230 %Fail, although there is some special treatment when Toplevel.debug is |
231 %enabled. |
231 %enabled. |
232 |
232 |
233 Most often you want to inspect data of Isabelle's basic data structures, |
233 Most often you want to inspect data of Isabelle's basic data structures, |
234 namely @{ML_type term}, @{ML_type typ}, @{ML_type cterm}, @{ML_type ctyp} |
234 namely @{ML_type term}, @{ML_type typ}, @{ML_type cterm}, @{ML_type ctyp} |
235 and @{ML_type thm}. Isabelle contains elaborate pretty-printing functions |
235 and @{ML_type thm}. Isabelle contains elaborate pretty-printing functions, |
236 for printing them (see Section \ref{sec:pretty}), but for quick-and-dirty |
236 which we will explain in more detail in Section \ref{sec:pretty}. For now |
237 solutions they are a bit unwieldy. One way to transform a term into a string |
237 we just use the functions @{ML_ind writeln in Pretty} from the structure |
238 is to use the function @{ML_ind string_of_term in Syntax} from the structure |
238 @{ML_struct Pretty} and @{ML_ind pretty_term in Syntax} from the structure |
239 @{ML_struct Syntax}. For more convenience, we bind this function to the |
239 @{ML_struct Syntax}. For more convenience, we bind them to the toplevel. |
240 toplevel. |
|
241 *} |
240 *} |
242 |
241 |
243 ML{*val string_of_term = Syntax.string_of_term*} |
242 ML{*val string_of_term = Syntax.string_of_term*} |
244 |
243 ML{*val pretty_term = Syntax.pretty_term*} |
245 text {* |
244 ML{*val pwriteln = Pretty.writeln*} |
246 It can now be used as follows |
245 |
|
246 text {* |
|
247 They can now be used as follows |
247 |
248 |
248 @{ML_response_fake [display,gray] |
249 @{ML_response_fake [display,gray] |
249 "string_of_term @{context} @{term \"1::nat\"}" |
250 "pwriteln (pretty_term @{context} @{term \"1::nat\"})" |
250 "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""} |
|
251 |
|
252 We obtain a string corrsponding to the term @{term [show_types] "1::nat"} with some |
|
253 additional information encoded in it. The string can be properly printed by |
|
254 using either the function @{ML writeln} or @{ML tracing}: |
|
255 |
|
256 @{ML_response_fake [display,gray] |
|
257 "writeln (string_of_term @{context} @{term \"1::nat\"})" |
|
258 "\"1\""} |
251 "\"1\""} |
259 |
252 |
260 or |
253 If there is more than one term to be printed, you can use the |
261 |
254 function @{ML_ind enum in Pretty} to separate them. |
262 @{ML_response_fake [display,gray] |
|
263 "tracing (string_of_term @{context} @{term \"1::nat\"})" |
|
264 "\"1\""} |
|
265 |
|
266 If there are more than one term to be printed, you can use the |
|
267 function @{ML_ind commas in Library} to separate them. |
|
268 *} |
255 *} |
269 |
256 |
270 ML{*fun string_of_terms ctxt ts = |
257 ML{*fun string_of_terms ctxt ts = |
271 commas (map (string_of_term ctxt) ts)*} |
258 commas (map (string_of_term ctxt) ts)*} |
272 |
259 ML{*fun pretty_terms ctxt ts = |
273 text {* |
260 Pretty.enum "," "" "" (map (pretty_term ctxt) ts)*} |
274 You can also print out terms together with typing information. |
261 |
|
262 text {* |
|
263 You can also print out terms together with their typing information. |
275 For this you need to set the reference @{ML_ind show_types in Syntax} |
264 For this you need to set the reference @{ML_ind show_types in Syntax} |
276 to @{ML true}. |
265 to @{ML true}. |
277 *} |
266 *} |
278 |
267 |
279 ML{*show_types := true*} |
268 ML{*show_types := true*} |
280 |
269 |
281 text {* |
270 text {* |
282 Now @{ML string_of_term} prints out |
271 Now @{ML pretty_term} prints out |
283 |
272 |
284 @{ML_response_fake [display, gray] |
273 @{ML_response_fake [display, gray] |
285 "tracing (string_of_term @{context} @{term \"(1::nat, x)\"})" |
274 "pwriteln (pretty_term @{context} @{term \"(1::nat, x)\"})" |
286 "(1::nat, x::'a)"} |
275 "(1::nat, x::'a)"} |
287 |
276 |
288 where @{text 1} and @{text x} are displayed with their inferred type. |
277 where @{text 1} and @{text x} are displayed with their inferred type. |
289 Even more type information can be printed by setting |
278 Even more type information can be printed by setting |
290 the reference @{ML_ind show_all_types in Syntax} to @{ML true}. |
279 the reference @{ML_ind show_all_types in Syntax} to @{ML true}. |
292 *} |
281 *} |
293 (*<*)ML %linenos {*show_all_types := true*} |
282 (*<*)ML %linenos {*show_all_types := true*} |
294 (*>*) |
283 (*>*) |
295 text {* |
284 text {* |
296 @{ML_response_fake [display, gray] |
285 @{ML_response_fake [display, gray] |
297 "tracing (string_of_term @{context} @{term \"(1::nat, x)\"})" |
286 "pwriteln (pretty_term @{context} @{term \"(1::nat, x)\"})" |
298 "(Pair::nat \<Rightarrow> 'a \<Rightarrow> nat \<times> 'a) (1::nat) (x::'a)"} |
287 "(Pair::nat \<Rightarrow> 'a \<Rightarrow> nat \<times> 'a) (1::nat) (x::'a)"} |
299 |
288 |
300 where @{term Pair} is the term-constructor for products. |
289 where @{term Pair} is the term-constructor for products. |
301 Other references that influence printing of terms are |
290 Other references that influence printing of terms are |
302 @{ML_ind show_brackets in Syntax} and @{ML_ind show_sorts in Syntax}. |
291 @{ML_ind show_brackets in Syntax} and @{ML_ind show_sorts in Syntax}. |
303 *} |
292 *} |
304 (*<*)ML %linenos {*show_types := false; show_all_types := false*} |
293 (*<*)ML %linenos {*show_types := false; show_all_types := false*} |
305 (*>*) |
294 (*>*) |
306 text {* |
295 text {* |
307 A @{ML_type cterm} can be transformed into a string by the following function. |
296 A @{ML_type cterm} can be printed with the following function. |
308 *} |
297 *} |
309 |
298 |
310 ML{*fun string_of_cterm ctxt ct = |
299 ML{*fun string_of_cterm ctxt ct = |
311 string_of_term ctxt (term_of ct)*} |
300 string_of_term ctxt (term_of ct)*} |
312 |
301 ML{*fun pretty_cterm ctxt ct = |
313 text {* |
302 pretty_term ctxt (term_of ct)*} |
314 In this example the function @{ML_ind term_of in Thm} extracts the @{ML_type |
303 |
315 term} from a @{ML_type cterm}. More than one @{ML_type cterm}s can again be |
304 text {* |
316 printed with @{ML commas}. |
305 Here the function @{ML_ind term_of in Thm} extracts the @{ML_type |
|
306 term} from a @{ML_type cterm}. More than one @{ML_type cterm}s can be |
|
307 printed again with @{ML enum in Pretty}. |
317 *} |
308 *} |
318 |
309 |
319 ML{*fun string_of_cterms ctxt cts = |
310 ML{*fun string_of_cterms ctxt cts = |
320 commas (map (string_of_cterm ctxt) cts)*} |
311 commas (map (string_of_cterm ctxt) cts)*} |
|
312 ML{*fun pretty_cterms ctxt cts = |
|
313 Pretty.enum "," "" "" (map (pretty_cterm ctxt) cts)*} |
321 |
314 |
322 text {* |
315 text {* |
323 The easiest way to get the string of a theorem is to transform it |
316 The easiest way to get the string of a theorem is to transform it |
324 into a @{ML_type term} using the function @{ML_ind prop_of in Thm}. |
317 into a @{ML_type term} using the function @{ML_ind prop_of in Thm}. |
325 *} |
318 *} |
326 |
319 |
327 ML{*fun string_of_thm ctxt thm = |
320 ML{*fun pretty_thm ctxt thm = |
328 string_of_term ctxt (prop_of thm)*} |
321 pretty_term ctxt (prop_of thm)*} |
329 |
322 |
330 text {* |
323 text {* |
331 Theorems include schematic variables, such as @{text "?P"}, |
324 Theorems include schematic variables, such as @{text "?P"}, |
332 @{text "?Q"} and so on. They are needed in Isabelle in order to able to |
325 @{text "?Q"} and so on. They are needed in Isabelle in order to able to |
333 instantiate theorems when they are applied. For example the theorem |
326 instantiate theorems when they are applied. For example the theorem |
334 @{thm [source] conjI} shown below can be used for any (typable) |
327 @{thm [source] conjI} shown below can be used for any (typable) |
335 instantiation of @{text "?P"} and @{text "?Q"}. |
328 instantiation of @{text "?P"} and @{text "?Q"}. |
336 |
329 |
337 @{ML_response_fake [display, gray] |
330 @{ML_response_fake [display, gray] |
338 "tracing (string_of_thm @{context} @{thm conjI})" |
331 "pwriteln (pretty_thm @{context} @{thm conjI})" |
339 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
332 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
340 |
333 |
341 However, in order to improve the readability when printing theorems, we |
334 However, in order to improve the readability when printing theorems, we |
342 convert these schematic variables into free variables using the function |
335 convert these schematic variables into free variables using the function |
343 @{ML_ind import in Variable}. This is similar to statements like @{text |
336 @{ML_ind import in Variable}. This is similar to statements like @{text |
349 val ((_, [thm']), _) = Variable.import true [thm] ctxt |
342 val ((_, [thm']), _) = Variable.import true [thm] ctxt |
350 in |
343 in |
351 thm' |
344 thm' |
352 end |
345 end |
353 |
346 |
354 fun string_of_thm_no_vars ctxt thm = |
347 fun pretty_thm_no_vars ctxt thm = |
355 string_of_term ctxt (prop_of (no_vars ctxt thm))*} |
348 pretty_term ctxt (prop_of (no_vars ctxt thm))*} |
|
349 |
356 |
350 |
357 text {* |
351 text {* |
358 With this function, theorem @{thm [source] conjI} is now printed as follows: |
352 With this function, theorem @{thm [source] conjI} is now printed as follows: |
359 |
353 |
360 @{ML_response_fake [display, gray] |
354 @{ML_response_fake [display, gray] |
361 "tracing (string_of_thm_no_vars @{context} @{thm conjI})" |
355 "pwriteln (pretty_thm_no_vars @{context} @{thm conjI})" |
362 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
356 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
363 |
357 |
364 Again the function @{ML commas} helps with printing more than one theorem. |
358 Again the function @{ML commas} helps with printing more than one theorem. |
365 *} |
359 *} |
366 |
360 |
367 ML{*fun string_of_thms ctxt thms = |
361 ML{*fun pretty_thms ctxt thms = |
368 commas (map (string_of_thm ctxt) thms) |
362 Pretty.enum "," "" "" (map (pretty_thm ctxt) thms) |
369 |
363 |
370 fun string_of_thms_no_vars ctxt thms = |
364 fun pretty_thms_no_vars ctxt thms = |
371 commas (map (string_of_thm_no_vars ctxt) thms) *} |
365 Pretty.enum "," "" "" (map (pretty_thm_no_vars ctxt) thms)*} |
372 |
366 |
373 text {* |
367 text {* |
374 The printing functions for types are |
368 The printing functions for types are |
375 *} |
369 *} |
376 |
370 |
377 ML{*fun string_of_typ ctxt ty = Syntax.string_of_typ ctxt ty |
371 ML{*fun pretty_typ ctxt ty = Syntax.pretty_typ ctxt ty |
378 fun string_of_typs ctxt tys = commas (map (string_of_typ ctxt) tys)*} |
372 fun pretty_typs ctxt tys = Pretty.commas (map (pretty_typ ctxt) tys)*} |
379 |
373 |
380 text {* |
374 text {* |
381 respectively ctypes |
375 respectively ctypes |
382 *} |
376 *} |
383 |
377 |
384 ML{*fun string_of_ctyp ctxt cty = string_of_typ ctxt (typ_of cty) |
378 ML{*fun pretty_ctyp ctxt cty = pretty_typ ctxt (typ_of cty) |
385 fun string_of_ctyps ctxt ctys = commas (map (string_of_ctyp ctxt) ctys)*} |
379 fun pretty_ctyps ctxt ctys = Pretty.commas (map (pretty_ctyp ctxt) ctys)*} |
386 |
380 |
387 text {* |
381 text {* |
388 \begin{readmore} |
382 \begin{readmore} |
389 The simple conversion functions from Isabelle's main datatypes to |
383 The simple conversion functions from Isabelle's main datatypes to |
390 @{ML_type string}s are implemented in @{ML_file "Pure/Syntax/syntax.ML"}. |
384 @{ML_type string}s are implemented in @{ML_file "Pure/Syntax/syntax.ML"}. |
396 together, like a warning message consisting of a term and its type, you |
390 together, like a warning message consisting of a term and its type, you |
397 should try to print these parcels together in a single string. Therefore do |
391 should try to print these parcels together in a single string. Therefore do |
398 \emph{not} print out information as |
392 \emph{not} print out information as |
399 |
393 |
400 @{ML_response_fake [display,gray] |
394 @{ML_response_fake [display,gray] |
401 "tracing \"First half,\"; |
395 "writeln \"First half,\"; |
402 tracing \"and second half.\"" |
396 writeln \"and second half.\"" |
403 "First half, |
397 "First half, |
404 and second half."} |
398 and second half."} |
405 |
399 |
406 but as a single string with appropriate formatting. For example |
400 but as a single string with appropriate formatting. For example |
407 |
401 |
408 @{ML_response_fake [display,gray] |
402 @{ML_response_fake [display,gray] |
409 "tracing (\"First half,\" ^ \"\\n\" ^ \"and second half.\")" |
403 "writeln (\"First half,\" ^ \"\\n\" ^ \"and second half.\")" |
410 "First half, |
404 "First half, |
411 and second half."} |
405 and second half."} |
412 |
406 |
413 To ease this kind of string manipulations, there are a number |
407 To ease this kind of string manipulations, there are a number |
414 of library functions in Isabelle. For example, the function |
408 of library functions in Isabelle. For example, the function |
415 @{ML_ind cat_lines in Library} concatenates a list of strings |
409 @{ML_ind cat_lines in Library} concatenates a list of strings |
416 and inserts newlines in between each element. |
410 and inserts newlines in between each element. |
417 |
411 |
418 @{ML_response_fake [display, gray] |
412 @{ML_response_fake [display, gray] |
419 "tracing (cat_lines [\"foo\", \"bar\"])" |
413 "writeln (cat_lines [\"foo\", \"bar\"])" |
420 "foo |
414 "foo |
421 bar"} |
415 bar"} |
422 |
416 |
423 Section \ref{sec:pretty} will explain the infrastructure that Isabelle |
417 Section \ref{sec:pretty} will explain the infrastructure that Isabelle |
424 provides for more elaborate pretty printing. |
418 provides for more elaborate pretty printing. |
425 |
419 |
426 \begin{readmore} |
420 \begin{readmore} |
427 Most of the basic string functions of Isabelle are defined in |
421 Most of the basic string functions of Isabelle are defined in |
428 @{ML_file "Pure/library.ML"}. |
422 @{ML_file "Pure/library.ML"}. |
429 \end{readmore} |
423 \end{readmore} |
430 |
|
431 *} |
424 *} |
432 |
425 |
433 |
426 |
434 section {* Combinators\label{sec:combinators} *} |
427 section {* Combinators\label{sec:combinators} *} |
435 |
428 |
895 and the second is a proof. For example |
888 and the second is a proof. For example |
896 *} |
889 *} |
897 |
890 |
898 ML{*val foo_thm = @{lemma "True" and "False \<Longrightarrow> P" by simp_all} *} |
891 ML{*val foo_thm = @{lemma "True" and "False \<Longrightarrow> P" by simp_all} *} |
899 |
892 |
|
893 ML {* |
|
894 pretty_thms_no_vars |
|
895 *} |
|
896 |
900 text {* |
897 text {* |
901 The result can be printed out as follows. |
898 The result can be printed out as follows. |
902 |
899 |
903 @{ML_response_fake [gray,display] |
900 @{ML_response_fake [gray,display] |
904 "foo_thm |> string_of_thms_no_vars @{context} |
901 "foo_thm |> pretty_thms_no_vars @{context} |
905 |> tracing" |
902 |> pwriteln" |
906 "True, False \<Longrightarrow> P"} |
903 "True, False \<Longrightarrow> P"} |
907 |
904 |
908 You can also refer to the current simpset via an antiquotation. To illustrate |
905 You can also refer to the current simpset via an antiquotation. To illustrate |
909 this we implement the function that extracts the theorem names stored in a |
906 this we implement the function that extracts the theorem names stored in a |
910 simpset. |
907 simpset. |