CookBook/FirstSteps.thy
changeset 186 371e4375c994
parent 185 043ef82000b4
child 188 8939b8fd8603
equal deleted inserted replaced
185:043ef82000b4 186:371e4375c994
   555 
   555 
   556 text {*
   556 text {*
   557   While antiquotations are very convenient for constructing terms, they can
   557   While antiquotations are very convenient for constructing terms, they can
   558   only construct fixed terms (remember they are ``linked'' at compile-time).
   558   only construct fixed terms (remember they are ``linked'' at compile-time).
   559   However, you often need to construct terms dynamically. For example, a
   559   However, you often need to construct terms dynamically. For example, a
   560   function that returns the implication @{text "\<And>(x::\<tau>). P x \<Longrightarrow> Q x"} taking
   560   function that returns the implication @{text "\<And>(x::nat). P x \<Longrightarrow> Q x"} taking
   561   @{term P}, @{term Q} and the type @{term "\<tau>"} as arguments can only be
   561   @{term P} and @{term Q} as arguments can only be written as:
   562   written as:
   562 
   563 
   563 *}
   564 *}
   564 
   565 
   565 ML{*fun make_imp P Q =
   566 ML{*fun make_imp P Q tau =
       
   567 let
   566 let
   568   val x = Free ("x", tau)
   567   val x = Free ("x", @{typ nat})
   569 in 
   568 in 
   570   Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   569   Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   571 end *}
   570 end *}
   572 
   571 
   573 text {*
   572 text {*
   574   The reason is that you cannot pass the arguments @{term P}, @{term Q} and 
   573   The reason is that you cannot pass the arguments @{term P} and @{term Q} 
   575   @{term "tau"} into an antiquotation. For example the following does \emph{not} work.
   574   into an antiquotation. For example the following does \emph{not} work.
   576 *}
   575 *}
   577 
   576 
   578 ML{*fun make_wrong_imp P Q tau = @{prop "\<And>x. P x \<Longrightarrow> Q x"} *}
   577 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *}
   579 
   578 
   580 text {*
   579 text {*
   581   To see this apply @{text "@{term S}"}, @{text "@{term T}"} and @{text "@{typ nat}"} 
   580   To see this apply @{text "@{term S}"} and @{text "@{term T}"} 
   582   to both functions. With @{ML make_imp} we obtain the intended term involving 
   581   to both functions. With @{ML make_imp} we obtain the intended term involving 
   583   the given arguments
   582   the given arguments
   584 
   583 
   585   @{ML_response [display,gray] "make_imp @{term S} @{term T} @{typ nat}" 
   584   @{ML_response [display,gray] "make_imp @{term S} @{term T}" 
   586 "Const \<dots> $ 
   585 "Const \<dots> $ 
   587   Abs (\"x\", Type (\"nat\",[]),
   586   Abs (\"x\", Type (\"nat\",[]),
   588     Const \<dots> $ (Free (\"S\",\<dots>) $ \<dots>) $ (Free (\"T\",\<dots>) $ \<dots>))"}
   587     Const \<dots> $ (Free (\"S\",\<dots>) $ \<dots>) $ (Free (\"T\",\<dots>) $ \<dots>))"}
   589 
   588 
   590   whereas with @{ML make_wrong_imp} we obtain a term involving the @{term "P"} 
   589   whereas with @{ML make_wrong_imp} we obtain a term involving the @{term "P"} 
   591   and @{text "Q"} from the antiquotation.
   590   and @{text "Q"} from the antiquotation.
   592 
   591 
   593   @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T} @{typ nat}" 
   592   @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T}" 
   594 "Const \<dots> $ 
   593 "Const \<dots> $ 
   595   Abs (\"x\", \<dots>,
   594   Abs (\"x\", \<dots>,
   596     Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   595     Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   597                (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   596                (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   598 
   597 
   599   (FIXME: handy functions for constructing terms: @{ML list_comb}, @{ML lambda})
   598   (FIXME: handy functions for constructing terms: @{ML list_comb}, @{ML lambda})
   600 
   599 *}
   601 
   600 
   602   Although types of terms can often be inferred, there are many
   601 
   603   situations where you need to construct types manually, especially  
   602 text {*
   604   when defining constants. For example the function returning a function 
       
   605   type is as follows:
       
   606 
       
   607 *} 
       
   608 
       
   609 ML{*fun make_fun_type tau1 tau2 = Type ("fun", [tau1, tau2]) *}
       
   610 
       
   611 text {* This can be equally written with the combinator @{ML "-->"} as: *}
       
   612 
       
   613 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *}
       
   614 
       
   615 text {*
       
   616   A handy function for manipulating terms is @{ML map_types}: it takes a 
       
   617   function and applies it to every type in a term. You can, for example,
       
   618   change every @{typ nat} in a term into an @{typ int} using the function:
       
   619 *}
       
   620 
       
   621 ML{*fun nat_to_int t =
       
   622   (case t of
       
   623      @{typ nat} => @{typ int}
       
   624    | Type (s, ts) => Type (s, map nat_to_int ts)
       
   625    | _ => t)*}
       
   626 
       
   627 text {*
       
   628   An example as follows:
       
   629 
       
   630 @{ML_response_fake [display,gray] 
       
   631 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
       
   632 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
       
   633            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
       
   634 
       
   635   \begin{readmore}
   603   \begin{readmore}
   636   There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and
   604   There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and
   637   @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms 
   605   @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms 
   638   and types easier.\end{readmore}
   606   and types easier.\end{readmore}
   639 
   607 
   750   strips off all qualifiers.
   718   strips off all qualifiers.
   751 
   719 
   752   \begin{readmore}
   720   \begin{readmore}
   753   Functions about naming are implemented in @{ML_file "Pure/General/name_space.ML"};
   721   Functions about naming are implemented in @{ML_file "Pure/General/name_space.ML"};
   754   functions about signatures in @{ML_file "Pure/sign.ML"}.
   722   functions about signatures in @{ML_file "Pure/sign.ML"}.
   755   
       
   756   \end{readmore}
   723   \end{readmore}
       
   724 
       
   725   Although types of terms can often be inferred, there are many
       
   726   situations where you need to construct types manually, especially  
       
   727   when defining constants. For example the function returning a function 
       
   728   type is as follows:
       
   729 
       
   730 *} 
       
   731 
       
   732 ML{*fun make_fun_type tau1 tau2 = Type ("fun", [tau1, tau2]) *}
       
   733 
       
   734 text {* This can be equally written with the combinator @{ML "-->"} as: *}
       
   735 
       
   736 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *}
       
   737 
       
   738 text {*
       
   739   A handy function for manipulating terms is @{ML map_types}: it takes a 
       
   740   function and applies it to every type in a term. You can, for example,
       
   741   change every @{typ nat} in a term into an @{typ int} using the function:
       
   742 *}
       
   743 
       
   744 ML{*fun nat_to_int t =
       
   745   (case t of
       
   746      @{typ nat} => @{typ int}
       
   747    | Type (s, ts) => Type (s, map nat_to_int ts)
       
   748    | _ => t)*}
       
   749 
       
   750 text {*
       
   751   An example as follows:
       
   752 
       
   753 @{ML_response_fake [display,gray] 
       
   754 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
       
   755 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
       
   756            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
       
   757 
       
   758   (FIXME: readmore about types)
   757 *}
   759 *}
   758 
   760 
   759 
   761 
   760 section {* Type-Checking *}
   762 section {* Type-Checking *}
   761 
   763 
   795 in
   797 in
   796   cterm_of @{theory} 
   798   cterm_of @{theory} 
   797       (Const (@{const_name plus}, natT --> natT --> natT) $ zero $ zero)
   799       (Const (@{const_name plus}, natT --> natT --> natT) $ zero $ zero)
   798 end" "0 + 0"}
   800 end" "0 + 0"}
   799 
   801 
   800   In Isabelle not just types need to be certified, but also types. For example, 
   802   In Isabelle not just terms need to be certified, but also types. For example, 
   801   you obtain the certified type for the Isablle type @{typ "nat \<Rightarrow> bool"} on 
   803   you obtain the certified type for the Isablle type @{typ "nat \<Rightarrow> bool"} on 
   802   the ML-level as follows:
   804   the ML-level as follows:
   803 
   805 
   804   @{ML_response_fake [display,gray]
   806   @{ML_response_fake [display,gray]
   805   "ctyp_of @{theory} (@{typ nat} --> @{typ bool})"
   807   "ctyp_of @{theory} (@{typ nat} --> @{typ bool})"
  1181 section {* Setups (TBD) *}
  1183 section {* Setups (TBD) *}
  1182 
  1184 
  1183 text {*
  1185 text {*
  1184   In the previous section we used \isacommand{setup} in order to make
  1186   In the previous section we used \isacommand{setup} in order to make
  1185   a theorem attribute known to Isabelle. What happens behind the scenes
  1187   a theorem attribute known to Isabelle. What happens behind the scenes
  1186   is that \isacommand{setup} expects a functions from @{ML_type theory}
  1188   is that \isacommand{setup} expects a functions of type 
  1187   to @{ML_type theory}: the input theory is the current theory and the 
  1189   @{ML_type "theory -> theory"}: the input theory is the current theory and the 
  1188   output the theory where the theory attribute has been stored.
  1190   output the theory where the theory attribute has been stored.
  1189   
  1191   
  1190   This is a fundamental principle in Isabelle. A similar situation occurs 
  1192   This is a fundamental principle in Isabelle. A similar situation occurs 
  1191   for example with declaring constants. The function that declares a 
  1193   for example with declaring constants. The function that declares a 
  1192   constant on the ML-level is @{ML Sign.add_consts_i}. Recall that ML-code 
  1194   constant on the ML-level is @{ML Sign.add_consts_i}. 
  1193   needs to be \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}.
  1195   If you write\footnote{Recall that ML-code  needs to be 
  1194   If you write 
  1196   enclosed in \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}.} 
  1195 *}  
  1197 *}  
  1196 
  1198 
  1197 ML{*Sign.add_consts_i [(Binding.name "BAR", @{typ "nat"}, NoSyn)] @{theory} *}
  1199 ML{*Sign.add_consts_i [(@{binding "BAR"}, @{typ "nat"}, NoSyn)] @{theory} *}
  1198 
  1200 
  1199 text {*
  1201 text {*
  1200   for declaring the constant @{text "BAR"} with type @{typ nat} and 
  1202   for declaring the constant @{text "BAR"} with type @{typ nat} and 
  1201   run the code, then you indeed obtain a theory as result. But if you 
  1203   run the code, then you indeed obtain a theory as result. But if you 
  1202   query the constant with \isacommand{term}
  1204   query the constant on the Isabelle level using the command \isacommand{term}
  1203 
  1205 
  1204   \begin{isabelle}
  1206   \begin{isabelle}
  1205   \isacommand{term}~@{text [quotes] "BAR"}\\
  1207   \isacommand{term}~@{text [quotes] "BAR"}\\
  1206   @{text "> \"BAR\" :: \"'a\""}
  1208   @{text "> \"BAR\" :: \"'a\""}
  1207   \end{isabelle}
  1209   \end{isabelle}
  1210   blue) of polymorphic type. The problem is that the ML-expression above did 
  1212   blue) of polymorphic type. The problem is that the ML-expression above did 
  1211   not register the declaration with the current theory. This is what the command
  1213   not register the declaration with the current theory. This is what the command
  1212   \isacommand{setup} is for. The constant is properly declared with
  1214   \isacommand{setup} is for. The constant is properly declared with
  1213 *}
  1215 *}
  1214 
  1216 
  1215 setup %gray {* Sign.add_consts_i [(Binding.name "BAR", @{typ "nat"}, NoSyn)] *}
  1217 setup %gray {* Sign.add_consts_i [(@{binding "BAR"}, @{typ "nat"}, NoSyn)] *}
  1216 
  1218 
  1217 text {* 
  1219 text {* 
  1218   Now 
  1220   Now 
  1219   
  1221   
  1220   \begin{isabelle}
  1222   \begin{isabelle}
  1264   oops
  1266   oops
  1265 
  1267 
  1266 (*
  1268 (*
  1267 setup {*   
  1269 setup {*   
  1268   Sign.add_consts_i [("foo", @{typ "nat"},NoSyn)] 
  1270   Sign.add_consts_i [("foo", @{typ "nat"},NoSyn)] 
  1269  #> PureThy.add_defs false [((Binding.name "foo_def", 
  1271  #> PureThy.add_defs false [((@{binding "foo_def"}, 
  1270        Logic.mk_equals (Const ("FirstSteps.foo", @{typ "nat"}), @{term "1::nat"})), [])] 
  1272        Logic.mk_equals (Const ("FirstSteps.foo", @{typ "nat"}), @{term "1::nat"})), [])] 
  1271  #> snd
  1273  #> snd
  1272 *}
  1274 *}
  1273 *)
  1275 *)
  1274 (*
  1276 (*