ProgTutorial/Advanced.thy
changeset 572 438703674711
parent 569 f875a25aa72d
equal deleted inserted replaced
571:95b42288294e 572:438703674711
   248   free variables as being alien or faulty.  Therefore the highlighting. 
   248   free variables as being alien or faulty.  Therefore the highlighting. 
   249   While this seems like a minor detail, the concept of making the context aware 
   249   While this seems like a minor detail, the concept of making the context aware 
   250   of fixed variables is actually quite useful. For example it prevents us from 
   250   of fixed variables is actually quite useful. For example it prevents us from 
   251   fixing a variable twice
   251   fixing a variable twice
   252 
   252 
   253   @{ML_matchresult_fake [gray, display]
   253   @{ML_response [gray, display]
   254   \<open>@{context}
   254   \<open>@{context}
   255 |> Variable.add_fixes ["x", "x"]\<close> 
   255 |> Variable.add_fixes ["x", "x"]\<close> 
   256   \<open>ERROR: Duplicate fixed variable(s): "x"\<close>}
   256   \<open>Duplicate fixed variable(s): "x"\<close>}
   257 
   257 
   258   More importantly it also allows us to easily create fresh names for
   258   More importantly it also allows us to easily create fresh names for
   259   fixed variables.  For this you have to use the function @{ML_ind
   259   fixed variables.  For this you have to use the function @{ML_ind
   260   variant_fixes in Variable} from the structure @{ML_structure Variable}.
   260   variant_fixes in Variable} from the structure @{ML_structure Variable}.
   261 
   261 
   262   @{ML_matchresult_fake [gray, display]
   262   @{ML_response [gray, display]
   263   \<open>@{context}
   263   \<open>@{context}
   264 |> Variable.variant_fixes ["y", "y", "z"]\<close> 
   264 |> Variable.variant_fixes ["y", "y", "z"]\<close> 
   265   \<open>(["y", "ya", "z"], ...)\<close>}
   265   \<open>(["y", "ya", "z"],\<dots>\<close>}
   266 
   266 
   267   Now a fresh variant for the second occurence of \<open>y\<close> is created
   267   Now a fresh variant for the second occurence of \<open>y\<close> is created
   268   avoiding any clash. In this way we can also create fresh free variables
   268   avoiding any clash. In this way we can also create fresh free variables
   269   that avoid any clashes with fixed variables. In Line~3 below we fix
   269   that avoid any clashes with fixed variables. In Line~3 below we fix
   270   the variable \<open>x\<close> in the context \<open>ctxt1\<close>. Next we want to
   270   the variable \<open>x\<close> in the context \<open>ctxt1\<close>. Next we want to
   271   create two fresh variables of type @{typ nat} as variants of the
   271   create two fresh variables of type @{typ nat} as variants of the
   272   string @{text [quotes] "x"} (Lines 6 and 7).
   272   string @{text [quotes] "x"} (Lines 6 and 7).
   273 
   273 
   274   @{ML_matchresult_fake [display, gray, linenos]
   274   @{ML_matchresult [display, gray, linenos]
   275   \<open>let
   275   \<open>let
   276   val ctxt0 = @{context}
   276   val ctxt0 = @{context}
   277   val (_, ctxt1) = Variable.add_fixes ["x"] ctxt0
   277   val (_, ctxt1) = Variable.add_fixes ["x"] ctxt0
   278   val frees = replicate 2 ("x", @{typ nat})
   278   val frees = replicate 2 ("x", @{typ nat})
   279 in
   279 in
   280   (Variable.variant_frees ctxt0 [] frees,
   280   (Variable.variant_frees ctxt0 [] frees,
   281    Variable.variant_frees ctxt1 [] frees)
   281    Variable.variant_frees ctxt1 [] frees)
   282 end\<close>
   282 end\<close>
   283   \<open>([("x", "nat"), ("xa", "nat")], 
   283   \<open>([("x", _), ("xa", _)], 
   284  [("xa", "nat"), ("xb", "nat")])\<close>}
   284  [("xa", _), ("xb", _)])\<close>}
   285 
   285 
   286   As you can see, if we create the fresh variables with the context \<open>ctxt0\<close>,
   286   As you can see, if we create the fresh variables with the context \<open>ctxt0\<close>,
   287   then we obtain \<open>x\<close> and \<open>xa\<close>; but in \<open>ctxt1\<close> we obtain \<open>xa\<close>
   287   then we obtain \<open>x\<close> and \<open>xa\<close>; but in \<open>ctxt1\<close> we obtain \<open>xa\<close>
   288   and \<open>xb\<close> avoiding \<open>x\<close>, which was fixed in this context.
   288   and \<open>xb\<close> avoiding \<open>x\<close>, which was fixed in this context.
   289 
   289 
   290   Often one has the problem that given some terms, create fresh variables
   290   Often one has the problem that given some terms, create fresh variables
   291   avoiding any variable occurring in those terms. For this you can use the
   291   avoiding any variable occurring in those terms. For this you can use the
   292   function @{ML_ind declare_term in Variable} from the structure @{ML_structure Variable}.
   292   function @{ML_ind declare_term in Variable} from the structure @{ML_structure Variable}.
   293 
   293 
   294   @{ML_matchresult_fake [gray, display]
   294   @{ML_matchresult [gray, display]
   295   \<open>let
   295   \<open>let
   296   val ctxt1 = Variable.declare_term @{term "(x, xa)"} @{context}
   296   val ctxt1 = Variable.declare_term @{term "(x, xa)"} @{context}
   297   val frees = replicate 2 ("x", @{typ nat})
   297   val frees = replicate 2 ("x", @{typ nat})
   298 in
   298 in
   299   Variable.variant_frees ctxt1 [] frees
   299   Variable.variant_frees ctxt1 [] frees
   300 end\<close>
   300 end\<close>
   301   \<open>[("xb", "nat"), ("xc", "nat")]\<close>}
   301   \<open>[("xb", _), ("xc", _)]\<close>}
   302 
   302 
   303   The result is \<open>xb\<close> and \<open>xc\<close> for the names of the fresh
   303   The result is \<open>xb\<close> and \<open>xc\<close> for the names of the fresh
   304   variables, since \<open>x\<close> and \<open>xa\<close> occur in the term we declared. 
   304   variables, since \<open>x\<close> and \<open>xa\<close> occur in the term we declared. 
   305   Note that @{ML_ind declare_term in Variable} does not fix the
   305   Note that @{ML_ind declare_term in Variable} does not fix the
   306   variables; it just makes them ``known'' to the context. You can see
   306   variables; it just makes them ``known'' to the context. You can see
   325   All variables are highligted, indicating that they are not
   325   All variables are highligted, indicating that they are not
   326   fixed. However, declaring a term is helpful when parsing terms using
   326   fixed. However, declaring a term is helpful when parsing terms using
   327   the function @{ML_ind read_term in Syntax} from the structure
   327   the function @{ML_ind read_term in Syntax} from the structure
   328   @{ML_structure Syntax}. Consider the following code:
   328   @{ML_structure Syntax}. Consider the following code:
   329 
   329 
   330   @{ML_matchresult_fake [gray, display]
   330   @{ML_response [gray, display]
   331   \<open>let
   331   \<open>let
   332   val ctxt0 = @{context}
   332   val ctxt0 = @{context}
   333   val ctxt1 = Variable.declare_term @{term "x::nat"} ctxt0
   333   val ctxt1 = Variable.declare_term @{term "x::nat"} ctxt0
   334 in
   334 in
   335   (Syntax.read_term ctxt0 "x", 
   335   (Syntax.read_term ctxt0 "x", 
   341   with a default polymorphic type, but in case of \<open>ctxt1\<close> we obtain a
   341   with a default polymorphic type, but in case of \<open>ctxt1\<close> we obtain a
   342   free variable of type @{typ nat} as previously declared. Which
   342   free variable of type @{typ nat} as previously declared. Which
   343   type the parsed term receives depends upon the last declaration that
   343   type the parsed term receives depends upon the last declaration that
   344   is made, as the next example illustrates.
   344   is made, as the next example illustrates.
   345 
   345 
   346   @{ML_matchresult_fake [gray, display]
   346   @{ML_response [gray, display]
   347   \<open>let
   347   \<open>let
   348   val ctxt1 = Variable.declare_term @{term "x::nat"} @{context}
   348   val ctxt1 = Variable.declare_term @{term "x::nat"} @{context}
   349   val ctxt2 = Variable.declare_term @{term "x::int"} ctxt1
   349   val ctxt2 = Variable.declare_term @{term "x::int"} ctxt1
   350 in
   350 in
   351   (Syntax.read_term ctxt1 "x", 
   351   (Syntax.read_term ctxt1 "x", 
   396   following code the function @{ML_ind make_thm in Skip_Proof} from the 
   396   following code the function @{ML_ind make_thm in Skip_Proof} from the 
   397   structure @{ML_structure Skip_Proof}. This function will turn an arbitray 
   397   structure @{ML_structure Skip_Proof}. This function will turn an arbitray 
   398   term, in our case @{term "P x y z x y z"}, into a theorem (disregarding 
   398   term, in our case @{term "P x y z x y z"}, into a theorem (disregarding 
   399   whether it is actually provable).
   399   whether it is actually provable).
   400 
   400 
   401   @{ML_matchresult_fake [display, gray]
   401   @{ML_response [display, gray]
   402   \<open>let
   402   \<open>let
   403   val thy = @{theory}
   403   val thy = @{theory}
   404   val ctxt0 = @{context}
   404   val ctxt0 = @{context}
   405   val (_, ctxt1) = Variable.add_fixes ["P", "x", "y", "z"] ctxt0 
   405   val (_, ctxt1) = Variable.add_fixes ["P", "x", "y", "z"] ctxt0 
   406   val foo_thm = Skip_Proof.make_thm thy @{prop "P x y z x y z"}
   406   val foo_thm = Skip_Proof.make_thm thy @{prop "P x y z x y z"}
   414   that exporting from one to another is not just restricted to
   414   that exporting from one to another is not just restricted to
   415   variables, but also works with assumptions. For this we can use the
   415   variables, but also works with assumptions. For this we can use the
   416   function @{ML_ind export in Assumption} from the structure
   416   function @{ML_ind export in Assumption} from the structure
   417   @{ML_structure Assumption}. Consider the following code.
   417   @{ML_structure Assumption}. Consider the following code.
   418 
   418 
   419   @{ML_matchresult_fake [display, gray, linenos]
   419   @{ML_response [display, gray, linenos]
   420   \<open>let
   420   \<open>let
   421   val ctxt0 = @{context}
   421   val ctxt0 = @{context}
   422   val ([eq], ctxt1) = Assumption.add_assumes [@{cprop "x \<equiv> y"}] ctxt0
   422   val ([eq], ctxt1) = Assumption.add_assumes [@{cprop "x \<equiv> y"}] ctxt0
   423   val eq' = Thm.symmetric eq
   423   val eq' = Thm.symmetric eq
   424 in
   424 in
   446   The function @{ML_ind export in Proof_Context} from the structure 
   446   The function @{ML_ind export in Proof_Context} from the structure 
   447   @{ML_structure Proof_Context} combines both export functions from 
   447   @{ML_structure Proof_Context} combines both export functions from 
   448   @{ML_structure Variable} and @{ML_structure Assumption}. This can be seen
   448   @{ML_structure Variable} and @{ML_structure Assumption}. This can be seen
   449   in the following example.
   449   in the following example.
   450 
   450 
   451   @{ML_matchresult_fake [display, gray]
   451   @{ML_response [display, gray]
   452   \<open>let
   452   \<open>let
   453   val ctxt0 = @{context}
   453   val ctxt0 = @{context}
   454   val ((fvs, [eq]), ctxt1) = ctxt0
   454   val ((fvs, [eq]), ctxt1) = ctxt0
   455     |> Variable.add_fixes ["x", "y"]
   455     |> Variable.add_fixes ["x", "y"]
   456     ||>> Assumption.add_assumes [@{cprop "x \<equiv> y"}]
   456     ||>> Assumption.add_assumes [@{cprop "x \<equiv> y"}]
   457   val eq' = Thm.symmetric eq
   457   val eq' = Thm.symmetric eq
   458 in
   458 in
   459   Proof_Context.export ctxt1 ctxt0 [eq']
   459   Proof_Context.export ctxt1 ctxt0 [eq']
   460 end\<close>
   460 end\<close>
   461   \<open>[?x \<equiv> ?y \<Longrightarrow> ?y \<equiv> ?x]\<close>}
   461   \<open>["?x \<equiv> ?y \<Longrightarrow> ?y \<equiv> ?x"]\<close>}
   462 \<close>
   462 \<close>
   463 
   463 
   464 
   464 
   465 
   465 
   466 text \<open>
   466 text \<open>