ProgTutorial/Advanced.thy
changeset 496 80eb66aefc66
parent 495 f3f24874e8be
child 497 76c632c05949
equal deleted inserted replaced
495:f3f24874e8be 496:80eb66aefc66
   214   txt_raw {*\mbox{}\\[-7mm]*}
   214   txt_raw {*\mbox{}\\[-7mm]*}
   215   ML_prf {* Variable.dest_fixes @{context} *} 
   215   ML_prf {* Variable.dest_fixes @{context} *} 
   216   txt_raw {*\mbox{}\\[-7mm] \ldots*}(*<*)oops(*>*)
   216   txt_raw {*\mbox{}\\[-7mm] \ldots*}(*<*)oops(*>*)
   217 
   217 
   218 text {*
   218 text {*
   219   The interesting point in this proof is that we injected ML-code before and after
   219   The interesting point is that we injected ML-code before and after
   220   the variables are fixed. For this remember that ML-code inside a proof
   220   the variables are fixed. For this remember that ML-code inside a proof
   221   needs to be enclosed inside \isacommand{ML\_prf}~@{text "\<verbopen> \<dots> \<verbclose>"},
   221   needs to be enclosed inside \isacommand{ML\_prf}~@{text "\<verbopen> \<dots> \<verbclose>"},
   222   not \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}. The function 
   222   not \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}. The function 
   223   @{ML_ind dest_fixes in Variable} from the structure @{ML_struct Variable} takes 
   223   @{ML_ind dest_fixes in Variable} from the structure @{ML_struct Variable} takes 
   224   a context and returns all its currently fixed variable (names). That 
   224   a context and returns all its currently fixed variable (names). That 
   245 text {*
   245 text {*
   246   Here the first time we call @{ML dest_fixes in Variable} we have four fixes variables;
   246   Here the first time we call @{ML dest_fixes in Variable} we have four fixes variables;
   247   the second time we get only the fixes variables @{text x} and @{text y} as answer, since
   247   the second time we get only the fixes variables @{text x} and @{text y} as answer, since
   248   @{text z} and @{text w} are not anymore in the scope of the context. 
   248   @{text z} and @{text w} are not anymore in the scope of the context. 
   249   This means the curly-braces act on the Isabelle level as opening and closing statements 
   249   This means the curly-braces act on the Isabelle level as opening and closing statements 
   250   for a context. The above proof fragment corresoponds roughly to the following ML-code
   250   for a context. The above proof fragment corresponds roughly to the following ML-code
   251 *}
   251 *}
   252 
   252 
   253 ML{*val ctxt0 = @{context};
   253 ML{*val ctxt0 = @{context};
   254 val ([x, y], ctxt1) = Variable.add_fixes ["x", "y"] ctxt0;
   254 val ([x, y], ctxt1) = Variable.add_fixes ["x", "y"] ctxt0;
   255 val ([z, w], ctxt2) = Variable.add_fixes ["z", "w"] ctxt1*}
   255 val ([z, w], ctxt2) = Variable.add_fixes ["z", "w"] ctxt1*}
   256 
   256 
   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. 
   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 
   263 
   263   \begin{isabelle}
   264   \begin{isabelle}
   264   \begin{graybox}
   265   \begin{graybox}
   265   @{ML "let
   266   @{ML "let
   266   val trm = @{term \"(x, y, z, w)\"}
   267   val trm = @{term \"(x, y, z, w)\"}
   286   \end{graybox}
   287   \end{graybox}
   287   \end{isabelle}
   288   \end{isabelle}
   288 
   289 
   289 
   290 
   290   The term we are printing is in all three cases the same---a tuple containing
   291   The term we are printing is in all three cases the same---a tuple containing
   291   four free variables. As you can see in case of @{ML "ctxt0"}, however, all
   292   four free variables. As you can see, however, in case of @{ML "ctxt0"} all
   292   variables are highlighted indicating a problem, while in case of @{ML
   293   variables are highlighted indicating a problem, while in case of @{ML
   293   "ctxt1"} @{text x} and @{text y} are printed as normal (blue) free
   294   "ctxt1"} @{text x} and @{text y} are printed as normal (blue) free
   294   variables, but not @{text z} and @{text w}. In the last case all variables
   295   variables, but not @{text z} and @{text w}. In the last case all variables
   295   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
   296   contains the information which variables are fixed, and designates all other
   297   contains the information which variables are fixed, and designates all other
   302   @{ML_response_fake [gray, display]
   303   @{ML_response_fake [gray, display]
   303   "@{context}
   304   "@{context}
   304 |> Variable.add_fixes [\"x\", \"x\"]" 
   305 |> Variable.add_fixes [\"x\", \"x\"]" 
   305   "ERROR: Duplicate fixed variable(s): \"x\""}
   306   "ERROR: Duplicate fixed variable(s): \"x\""}
   306 
   307 
   307   But 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 
   308   clashes. 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
   309   @{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}
   310   as variants of the string @{text [quotes] "x"}.
   311   as variants of the string @{text [quotes] "x"}.
   311 
   312 
   312   @{ML_response_fake [display, gray, linenos]
   313   @{ML_response_fake [display, gray, linenos]
   313   "let
   314   "let
   319    Variable.variant_frees ctxt1 [] frees)
   320    Variable.variant_frees ctxt1 [] frees)
   320 end"
   321 end"
   321   "([(\"x\", \"nat\"), (\"xa\", \"nat\")], 
   322   "([(\"x\", \"nat\"), (\"xa\", \"nat\")], 
   322  [(\"xa\", \"nat\"), (\"xb\", \"nat\")])"}
   323  [(\"xa\", \"nat\"), (\"xb\", \"nat\")])"}
   323 
   324 
   324   As can be seen, if we create the fresh variables with the context @{text ctxt0},
   325   As you can see, if we create the fresh variables with the context @{text ctxt0},
   325   then we obtain @{text "x"} and @{text "xa"}; but in @{text ctxt1} we obtain @{text "xa"}
   326   then we obtain @{text "x"} and @{text "xa"}; but in @{text ctxt1} we obtain @{text "xa"}
   326   and @{text "xb"} avoiding @{text x}, which was fixed in this context.
   327   and @{text "xb"} avoiding @{text x}, which was fixed in this context.
   327 
   328 
   328   Often one has the situation that given some terms, create fresh variables
   329   Often one has the problem that given some terms, create fresh variables
   329   avoiding any variable occuring in those terms. For this you can use the
   330   avoiding any variable occurring in those terms. For this you can use the
   330   function @{ML_ind declare_term in Variable} from the structure @{ML_struct Variable}.
   331   function @{ML_ind declare_term in Variable} from the structure @{ML_struct Variable}.
   331 
   332 
   332   @{ML_response_fake [gray, display]
   333   @{ML_response_fake [gray, display]
   333   "let
   334   "let
   334   val ctxt1 = Variable.declare_term @{term \"(x, xa)\"} @{context}
   335   val ctxt1 = Variable.declare_term @{term \"(x, xa)\"} @{context}
   336 in
   337 in
   337   Variable.variant_frees ctxt1 [] frees
   338   Variable.variant_frees ctxt1 [] frees
   338 end"
   339 end"
   339   "[(\"xb\", \"nat\"), (\"xc\", \"nat\")]"}
   340   "[(\"xb\", \"nat\"), (\"xc\", \"nat\")]"}
   340 
   341 
   341   The result is @{text xb} and @{text xc} for the names of the freshh variables. This 
   342   The result is @{text xb} and @{text xc} for the names of the fresh
   342   is also important when parsing terms, for example with the function 
   343   variables. Note that @{ML_ind declare_term in Variable} does not fix the
   343   @{ML_ind read_term in Syntax} from the structure @{ML_struct Syntax}. Consider 
   344   variables; it just makes them ``known'' to the context. This is helpful when
   344   the following code:
   345   parsing terms using the function @{ML_ind read_term in Syntax} from the
       
   346   structure @{ML_struct Syntax}. Consider the following code:
   345 
   347 
   346   @{ML_response_fake [gray, display]
   348   @{ML_response_fake [gray, display]
   347   "let
   349   "let
   348   val ctxt0 = @{context}
   350   val ctxt0 = @{context}
   349   val ctxt1 = Variable.declare_term @{term \"x::nat\"} ctxt0
   351   val ctxt1 = Variable.declare_term @{term \"x::nat\"} ctxt0
   351   (Syntax.read_term ctxt0 \"x\", 
   353   (Syntax.read_term ctxt0 \"x\", 
   352    Syntax.read_term ctxt1 \"x\") 
   354    Syntax.read_term ctxt1 \"x\") 
   353 end"
   355 end"
   354   "(Free (\"x\", \"'a\"), Free (\"x\", \"nat\"))"}
   356   "(Free (\"x\", \"'a\"), Free (\"x\", \"nat\"))"}
   355   
   357   
   356   Parsing the string in the first context results in a free variable 
   358   Parsing the string in the context @{text "ctxt0"} results in a free variable 
   357   with a default polymorphic type, but in the second case we obtain a
   359   with a default polymorphic type, but in case of @{text "ctxt1"} we obtain a
   358   free variable of type @{typ nat} as previously declared. Which
   360   free variable of type @{typ nat} as previously declared. Which
   359   type the parsed term receives depends on the last declaration that
   361   type the parsed term receives depends upon the last declaration that
   360   is made as the next example illustrates.
   362   is made, as the next example illustrates.
   361 
   363 
   362   @{ML_response_fake [gray, display]
   364   @{ML_response_fake [gray, display]
   363   "let
   365   "let
   364   val ctxt1 = Variable.declare_term @{term \"x::nat\"} @{context}
   366   val ctxt1 = Variable.declare_term @{term \"x::nat\"} @{context}
   365   val ctxt2 = Variable.declare_term @{term \"x::int\"} ctxt1
   367   val ctxt2 = Variable.declare_term @{term \"x::int\"} ctxt1
   367   (Syntax.read_term ctxt1 \"x\", 
   369   (Syntax.read_term ctxt1 \"x\", 
   368    Syntax.read_term ctxt2 \"x\") 
   370    Syntax.read_term ctxt2 \"x\") 
   369 end"
   371 end"
   370   "(Free (\"x\", \"nat\"), Free (\"x\", \"int\"))"}
   372   "(Free (\"x\", \"nat\"), Free (\"x\", \"int\"))"}
   371 
   373 
       
   374   The most useful feature of contexts is that one can export, for example,
       
   375   terms between contexts.
   372 *}
   376 *}
   373 
   377 
   374 ML {*
   378 ML {*
   375 let
   379 let
   376   val ctxt0 = @{context}
   380   val ctxt0 = @{context}
   377   val trm = @{prop "P x y z"}
       
   378   val foo_thm = Skip_Proof.make_thm (Proof_Context.theory_of ctxt0) trm
       
   379   val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 
   381   val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 
       
   382   val foo_trm = @{term "P x y z"}
       
   383 in
       
   384   singleton (Variable.export_terms ctxt1 ctxt0) foo_trm
       
   385   |> pretty_term ctxt1
       
   386   |> pwriteln
       
   387 end
       
   388 *}
       
   389 
       
   390 ML {*
       
   391 let
       
   392   val thy = @{theory}
       
   393   val ctxt0 = @{context}
       
   394   val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 
       
   395   val foo_thm = Skip_Proof.make_thm thy @{prop "P x y z"}
       
   396 in
       
   397   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
       
   398 end
       
   399 *}
       
   400 
       
   401 ML {*
       
   402 let
       
   403   val thy = @{theory}
       
   404   val ctxt0 = @{context}
       
   405   val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 
       
   406   val foo_thm = Skip_Proof.make_thm thy @{prop "P x y z"}
   380 in
   407 in
   381   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
   408   singleton (Proof_Context.export ctxt1 ctxt0) foo_thm
   382 end
   409 end
   383 *}
   410 *}
   384 
   411