ProgTutorial/Advanced.thy
changeset 498 7294b1b839a8
parent 497 76c632c05949
child 499 42bac8b16951
equal deleted inserted replaced
497:76c632c05949 498:7294b1b839a8
   159 *}
   159 *}
   160 
   160 
   161 setup %graylinenos {* fn thy => 
   161 setup %graylinenos {* fn thy => 
   162 let
   162 let
   163   val tmp_thy = Theory.copy thy
   163   val tmp_thy = Theory.copy thy
   164   val foo_const = ((@{binding "FOO"}, @{typ "nat => nat"}), NoSyn)
   164   val foo_const = ((@{binding "FOO"}, @{typ "nat \<Rightarrow> nat"}), NoSyn)
   165   val (_, tmp_thy') = Sign.declare_const @{context} foo_const tmp_thy
   165   val (_, tmp_thy') = Sign.declare_const @{context} foo_const tmp_thy
   166   val trm1 = Syntax.read_term_global tmp_thy' "FOO baz"
   166   val trm1 = Syntax.read_term_global tmp_thy' "FOO baz"
   167   val trm2 = Syntax.read_term_global thy "FOO baz"
   167   val trm2 = Syntax.read_term_global thy "FOO baz"
   168   val _ = writeln (@{make_string} trm1 ^ "\n" ^ @{make_string} trm2)
   168   val _ = writeln (@{make_string} trm1 ^ "\n" ^ @{make_string} trm2)
   169 in
   169 in
   257 text {*
   257 text {*
   258   where the function @{ML_ind add_fixes in Variable} fixes a list of variables
   258   where the function @{ML_ind add_fixes in Variable} fixes a list of variables
   259   specified by strings. Let us come back to the point about printing terms. Consider
   259   specified by strings. Let us come back to the point about printing terms. Consider
   260   printing out the term \mbox{@{text "(x, y, z, w)"}} using our function @{ML_ind pretty_term}.
   260   printing out the term \mbox{@{text "(x, y, z, w)"}} using our function @{ML_ind pretty_term}.
   261   This function takes a term and a context as argument. Notice how the printing
   261   This function takes a term and a context as argument. Notice how the printing
   262   of the term changes with which context is used.
   262   of the term changes according to which context is used.
   263 
   263 
   264   \begin{isabelle}
   264   \begin{isabelle}
   265   \begin{graybox}
   265   \begin{graybox}
   266   @{ML "let
   266   @{ML "let
   267   val trm = @{term \"(x, y, z, w)\"}
   267   val trm = @{term \"(x, y, z, w)\"}
   296   are printed as expected. The point of this example is that the context
   296   are printed as expected. The point of this example is that the context
   297   contains the information which variables are fixed, and designates all other
   297   contains the information which variables are fixed, and designates all other
   298   free variables as being alien or faulty.  Therefore the highlighting. 
   298   free variables as being alien or faulty.  Therefore the highlighting. 
   299   While this seems like a minor detail, the concept of making the context aware 
   299   While this seems like a minor detail, the concept of making the context aware 
   300   of fixed variables is actually quite useful. For example it prevents us from 
   300   of fixed variables is actually quite useful. For example it prevents us from 
   301   fixing a variable twice
   301   fixing a variable twice.
   302 
   302 
   303   @{ML_response_fake [gray, display]
   303   @{ML_response_fake [gray, display]
   304   "@{context}
   304   "@{context}
   305 |> Variable.add_fixes [\"x\", \"x\"]" 
   305 |> Variable.add_fixes [\"x\", \"x\"]" 
   306   "ERROR: Duplicate fixed variable(s): \"x\""}
   306   "ERROR: Duplicate fixed variable(s): \"x\""}
   307 
   307 
   308   More importantly it also allows us to easily create fresh free variables avoiding any 
   308   More importantly it also allows us to easily create fresh free variables avoiding any 
   309   clashes with fixed variables. In Line~3 below we fix the variable @{text x} in the context
   309   clashes with fixed variables. In Line~3 below we fix the variable @{text x} in the context
   310   @{text ctxt1}. Next we want to create two fresh variables of type @{typ nat}
   310   @{text ctxt1}. Next we want to create two fresh variables of type @{typ nat}
   311   as variants of the string @{text [quotes] "x"}.
   311   as variants of the string @{text [quotes] "x"} (Lines 6 and 7).
   312 
   312 
   313   @{ML_response_fake [display, gray, linenos]
   313   @{ML_response_fake [display, gray, linenos]
   314   "let
   314   "let
   315   val ctxt0 = @{context}
   315   val ctxt0 = @{context}
   316   val (_, ctxt1) = Variable.add_fixes [\"x\"] ctxt0
   316   val (_, ctxt1) = Variable.add_fixes [\"x\"] ctxt0
   338   Variable.variant_frees ctxt1 [] frees
   338   Variable.variant_frees ctxt1 [] frees
   339 end"
   339 end"
   340   "[(\"xb\", \"nat\"), (\"xc\", \"nat\")]"}
   340   "[(\"xb\", \"nat\"), (\"xc\", \"nat\")]"}
   341 
   341 
   342   The result is @{text xb} and @{text xc} for the names of the fresh
   342   The result is @{text xb} and @{text xc} for the names of the fresh
   343   variables. Note that @{ML_ind declare_term in Variable} does not fix the
   343   variables, since @{text x} and @{text xa} occur in the term we declared. 
   344   variables; it just makes them ``known'' to the context. This is helpful when
   344   Note that @{ML_ind declare_term in Variable} does not fix the
   345   parsing terms using the function @{ML_ind read_term in Syntax} from the
   345   variables; it just makes them ``known'' to the context. You can see
   346   structure @{ML_struct Syntax}. Consider the following code:
   346   that if you print out a declared term.
       
   347 
       
   348   \begin{isabelle}
       
   349   \begin{graybox}
       
   350   @{ML "let
       
   351   val trm = @{term \"P x y z\"}
       
   352   val ctxt1 = Variable.declare_term trm @{context}
       
   353 in
       
   354   pwriteln (pretty_term ctxt1 trm)
       
   355 end"}\\
       
   356   \setlength{\fboxsep}{0mm}
       
   357   @{text ">"}~\colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text P}}}~%
       
   358   \colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text x}}}~%
       
   359   \colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text y}}}~%
       
   360   \colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text z}}}
       
   361   \end{graybox}
       
   362   \end{isabelle}
       
   363 
       
   364   All variables are highligted, indicating that they are not
       
   365   fixed. However, declaring a term is helpful when parsing terms using
       
   366   the function @{ML_ind read_term in Syntax} from the structure
       
   367   @{ML_struct Syntax}. Consider the following code:
   347 
   368 
   348   @{ML_response_fake [gray, display]
   369   @{ML_response_fake [gray, display]
   349   "let
   370   "let
   350   val ctxt0 = @{context}
   371   val ctxt0 = @{context}
   351   val ctxt1 = Variable.declare_term @{term \"x::nat\"} ctxt0
   372   val ctxt1 = Variable.declare_term @{term \"x::nat\"} ctxt0
   370    Syntax.read_term ctxt2 \"x\") 
   391    Syntax.read_term ctxt2 \"x\") 
   371 end"
   392 end"
   372   "(Free (\"x\", \"nat\"), Free (\"x\", \"int\"))"}
   393   "(Free (\"x\", \"nat\"), Free (\"x\", \"int\"))"}
   373 
   394 
   374   The most useful feature of contexts is that one can export terms and theorems 
   395   The most useful feature of contexts is that one can export terms and theorems 
   375   between contexts. Let us consider first the case of terms. 
   396   between them. Let us show this first in the case of terms. 
   376 
   397 
   377   \begin{isabelle}
   398   \begin{isabelle}
   378   \begin{graybox}
   399   \begin{graybox}
   379   \begin{linenos}
   400   \begin{linenos}
   380   @{ML "let
   401   @{ML "let
   391   @{text ">"}~\colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text P}}}~%
   412   @{text ">"}~\colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text P}}}~%
   392   @{text "?x ?y ?z"}
   413   @{text "?x ?y ?z"}
   393   \end{graybox}
   414   \end{graybox}
   394   \end{isabelle}
   415   \end{isabelle}
   395 
   416 
   396   In Line 3 we fix the variables @{term x}, @{term y} and @{term z} in context @{text ctxt1}.
   417   In Line 3 we fix the variables @{term x}, @{term y} and @{term z} in
   397   The function @{ML_ind export_terms in Variable} from the @{ML_struct Variable} can be used 
   418   context @{text ctxt1}.  The function @{ML_ind export_terms in
   398   to ``transfer'' terms between contexts. Transferring means to turn all (free) variables that
   419   Variable} from the @{ML_struct Variable} can be used to ``transfer''
   399   are fixed in one context, but not in the other, into schematic variables. In our example
   420   terms between contexts. Transferring means to turn all (free)
   400   we are transferring the term @{text "P x y z"} from context @{text "ctxt1"} into @{text "ctxt0"}
   421   variables that are fixed in one context, but not in the other, into
   401   which means @{term x}, @{term y} and @{term z} become schematic variables (as can be seen 
   422   schematic variables. In our example, we are transferring the term
   402   by the leading question mark). Note that the variable @{text P} stays a free variable, since 
   423   @{text "P x y z"} from context @{text "ctxt1"} to @{text "ctxt0"},
   403   it not fixed in @{text ctxt1}; it is even highlighed, because @{text "ctxt0"} does not
   424   which means @{term x}, @{term y} and @{term z} become schematic
   404   know about it. Note also that in Line 6 we had to use the function @{ML_ind singleton}, 
   425   variables (as can be seen by the leading question marks). Note that
   405   because the function @{ML_ind export_terms in Variable} normally works over lists of terms.
   426   the variable @{text P} stays a free variable, since it not fixed in
   406   
   427   @{text ctxt1}; it is even highlighed, because @{text "ctxt0"} does
   407   
   428   not know about it. Note also that in Line 6 we had to use the
   408 *}
   429   function @{ML_ind singleton}, because the function @{ML_ind
   409 
   430   export_terms in Variable} normally works over lists of terms.
   410 ML {*
   431 
   411 let
   432   The case of transferring theorems is even more useful. The reason is
       
   433   that the generalisation of fixed variables to schematic variables is
       
   434   not trivial. For illustration purposes we use in the following code
       
   435   the function @{ML_ind make_thm in Skip_Proof} from the structure
       
   436   @{ML_struct Skip_Proof} in order to turn an arbitray term into a
       
   437   theorem.
       
   438 
       
   439   @{ML_response_fake [display, gray]
       
   440   "let
       
   441   val thy = @{theory}
   412   val ctxt0 = @{context}
   442   val ctxt0 = @{context}
   413   val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 
   443   val (_, ctxt1) = Variable.add_fixes [\"x\", \"y\", \"z\"] ctxt0 
   414   val foo_trm = @{term "P x y z"}
   444   val foo_thm = Skip_Proof.make_thm thy @{prop \"P x y z x y z\"}
   415 in
   445 in
   416   singleton (Variable.export_terms ctxt1 ctxt0) foo_trm
   446   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
   417   |> pretty_term ctxt1
   447 end"
   418   |> pwriteln
   448   "> P ?x ?y ?z ?x ?y ?z"}
   419 end
   449 *}
   420 *}
   450 
   421 
   451 
   422 ML {*
   452 ML {*
   423 let
   453 let
   424   val thy = @{theory}
   454   val thy = @{theory}
   425   val ctxt0 = @{context}
   455   val ctxt0 = @{context}
   428 in
   458 in
   429   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
   459   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
   430 end
   460 end
   431 *}
   461 *}
   432 
   462 
   433 ML {*
       
   434 let
       
   435   val thy = @{theory}
       
   436   val ctxt0 = @{context}
       
   437   val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 
       
   438   val foo_thm = Skip_Proof.make_thm thy @{prop "P x y z"}
       
   439 in
       
   440   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
       
   441 end
       
   442 *}
       
   443 
   463 
   444 text {*
   464 text {*
   445 
   465 
   446 *}
   466 *}
   447 
   467