ProgTutorial/FirstSteps.thy
changeset 440 a0b280dd4bc7
parent 423 0a25b35178c3
equal deleted inserted replaced
439:b83c75d051b7 440:a0b280dd4bc7
   122   \isacommand{begin}\\
   122   \isacommand{begin}\\
   123   \ldots
   123   \ldots
   124   \end{tabular}
   124   \end{tabular}
   125   \end{quote}
   125   \end{quote}
   126 
   126 
   127   Note that no parentheses are given this time. Note also that the included
   127   Note that no parentheses are given in this case. Note also that the included
   128   ML-file should not contain any \isacommand{use} itself. Otherwise Isabelle
   128   ML-file should not contain any \isacommand{use} itself. Otherwise Isabelle
   129   is unable to record all file dependencies, which is a nuisance if you have
   129   is unable to record all file dependencies, which is a nuisance if you have
   130   to track down errors.
   130   to track down errors.
   131 *}
   131 *}
   132 
   132 
   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.