CookBook/FirstSteps.thy
changeset 89 fee4942c4770
parent 87 90189a97b3f8
child 92 4e3f262a459d
equal deleted inserted replaced
88:ebbd0dd008c8 89:fee4942c4770
     5 chapter {* First Steps *}
     5 chapter {* First Steps *}
     6 
     6 
     7 text {*
     7 text {*
     8 
     8 
     9   Isabelle programming is done in ML.  Just like lemmas and proofs, ML-code
     9   Isabelle programming is done in ML.  Just like lemmas and proofs, ML-code
    10   in Isabelle is part of a theory. If you want to follow the code written in
    10   in Isabelle is part of a theory. If you want to follow the code given in
    11   this chapter, we assume you are working inside the theory starting with
    11   this chapter, we assume you are working inside the theory starting with
    12 
    12 
    13   \begin{center}
    13   \begin{center}
    14   \begin{tabular}{@ {}l}
    14   \begin{tabular}{@ {}l}
    15   \isacommand{theory} FirstSteps\\
    15   \isacommand{theory} FirstSteps\\
    24 
    24 
    25 
    25 
    26 
    26 
    27 text {*
    27 text {*
    28   The easiest and quickest way to include code in a theory is
    28   The easiest and quickest way to include code in a theory is
    29   by using the \isacommand{ML}-command. For example\smallskip
    29   by using the \isacommand{ML}-command. For example:
    30 
    30 
    31 \begin{isabelle}
    31 \begin{isabelle}
    32 \begin{graybox}
    32 \begin{graybox}
    33 \isacommand{ML}~@{text "\<verbopen>"}\isanewline
    33 \isacommand{ML}~@{text "\<verbopen>"}\isanewline
    34 \hspace{5mm}@{ML "3 + 4"}\isanewline
    34 \hspace{5mm}@{ML "3 + 4"}\isanewline
    35 @{text "\<verbclose>"}\isanewline
    35 @{text "\<verbclose>"}\isanewline
    36 @{text "> 7"}\smallskip
    36 @{text "> 7"}\smallskip
    37 \end{graybox}
    37 \end{graybox}
    38 \end{isabelle}
    38 \end{isabelle}
    39 
    39 
    40   Like ``normal'' Isabelle proof scripts, 
    40   Like normal Isabelle proof scripts, 
    41   \isacommand{ML}-commands can be evaluated by using the advance and undo buttons of 
    41   \isacommand{ML}-commands can be evaluated by using the advance and undo buttons of 
    42   your Isabelle environment. The code inside the \isacommand{ML}-command 
    42   your Isabelle environment. The code inside the \isacommand{ML}-command 
    43   can also contain value and function bindings, and even those can be
    43   can also contain value and function bindings, and even those can be
    44   undone when the proof script is retracted. As mentioned earlier, we will  
    44   undone when the proof script is retracted. As mentioned earlier, we will  
    45   drop the \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"} 
    45   drop the \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"} 
    46   whenever we show code.
    46   scaffolding whenever we show code.
    47 
    47 
    48   Once a portion of code is relatively stable, one usually wants to 
    48   Once a portion of code is relatively stable, one usually wants to 
    49   export it to a separate ML-file. Such files can then be included in a 
    49   export it to a separate ML-file. Such files can then be included in a 
    50   theory by using \isacommand{uses} in the header of the theory, like
    50   theory by using the \isacommand{uses}-command in the header of the theory, like:
    51 
    51 
    52   \begin{center}
    52   \begin{center}
    53   \begin{tabular}{@ {}l}
    53   \begin{tabular}{@ {}l}
    54   \isacommand{theory} FirstSteps\\
    54   \isacommand{theory} FirstSteps\\
    55   \isacommand{imports} Main\\
    55   \isacommand{imports} Main\\
    83 
    83 
    84   The function @{ML "warning"} should only be used for testing purposes, because any
    84   The function @{ML "warning"} should only be used for testing purposes, because any
    85   output this function generates will be overwritten as soon as an error is
    85   output this function generates will be overwritten as soon as an error is
    86   raised. For printing anything more serious and elaborate, the
    86   raised. For printing anything more serious and elaborate, the
    87   function @{ML tracing} is more appropriate. This function writes all output into
    87   function @{ML tracing} is more appropriate. This function writes all output into
    88   a separate tracing buffer. For example
    88   a separate tracing buffer. For example:
    89 
    89 
    90   @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""}
    90   @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""}
    91 
    91 
    92   It is also possible to redirect the ``channel'' where the string @{text "foo"} is 
    92   It is also possible to redirect the ``channel'' where the string @{text "foo"} is 
    93   printed to a separate file, e.g.~to prevent ProofGeneral from choking on massive 
    93   printed to a separate file, e.g.~to prevent ProofGeneral from choking on massive 
   109 
   109 
   110 text {*
   110 text {*
   111   Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} 
   111   Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} 
   112   will cause that all tracing information is printed into the file @{text "foo.bar"}.
   112   will cause that all tracing information is printed into the file @{text "foo.bar"}.
   113 
   113 
   114   Error messages can be printed using the function @{ML error}, as in
   114   You can print out error messages with the function @{ML error}, as in:
   115 
   115 
   116   @{ML_response_fake [display,gray] "if 0=1 then 1 else (error \"foo\")" "\"foo\""}
   116   @{ML_response_fake [display,gray] "if 0=1 then 1 else (error \"foo\")" "\"foo\""}
   117 
   117 
   118 *}
   118 *}
   119 
   119 
   132   
   132   
   133   @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""}
   133   @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""}
   134  
   134  
   135   where @{text "@{theory}"} is an antiquotation that is substituted with the
   135   where @{text "@{theory}"} is an antiquotation that is substituted with the
   136   current theory (remember that we assumed we are inside the theory 
   136   current theory (remember that we assumed we are inside the theory 
   137   @{text FirstSteps}). The name of this theory can be extracted with
   137   @{text FirstSteps}). The name of this theory can be extracted using
   138   the function @{ML "Context.theory_name"}. 
   138   the function @{ML "Context.theory_name"}. 
   139 
   139 
   140   Note, however, that antiquotations are statically scoped, that is their value is
   140   Note, however, that antiquotations are statically linked, that is their value is
   141   determined at ``compile-time'', not ``run-time''. For example the function
   141   determined at ``compile-time'', not ``run-time''. For example the function
   142 *}
   142 *}
   143 
   143 
   144 ML{*fun not_current_thyname () = Context.theory_name @{theory} *}
   144 ML{*fun not_current_thyname () = Context.theory_name @{theory} *}
   145 
   145 
   146 text {*
   146 text {*
   147 
   147 
   148   does, as its name suggest, \emph{not} return the name of the current theory, if it is run in a 
   148   does \emph{not} return the name of the current theory, if it is run in a 
   149   different theory. Instead, the code above defines the constant function 
   149   different theory. Instead, the code above defines the constant function 
   150   that always returns the string @{text [quotes] "FirstSteps"}, no matter where the
   150   that always returns the string @{text [quotes] "FirstSteps"}, no matter where the
   151   function is called. Operationally speaking,  the antiquotation @{text "@{theory}"} is 
   151   function is called. Operationally speaking,  the antiquotation @{text "@{theory}"} is 
   152   \emph{not} replaced with code that will look up the current theory in 
   152   \emph{not} replaced with code that will look up the current theory in 
   153   some data structure and return it. Instead, it is literally
   153   some data structure and return it. Instead, it is literally
   159 
   159 
   160   or simpsets:
   160   or simpsets:
   161 
   161 
   162   @{ML_response_fake [display,gray] 
   162   @{ML_response_fake [display,gray] 
   163 "let
   163 "let
   164   val ({rules,...},_) = MetaSimplifier.rep_ss @{simpset}
   164   val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset}
   165 in
   165 in
   166   map #name (Net.entries rules)
   166   map #name (Net.entries rules)
   167 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   167 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   168 
   168 
   169   The code about simpsets extracts the theorem names that are stored in the
   169   The code about simpsets extracts the theorem names stored in the
   170   current simpset.  We get hold of the current simpset with the antiquotation 
   170   current simpset.  We get hold of the current simpset with the antiquotation 
   171   @{text "@{simpset}"}.  The function @{ML rep_ss in MetaSimplifier} returns a record
   171   @{text "@{simpset}"}.  The function @{ML rep_ss in MetaSimplifier} returns a record
   172   containing all information about the simpset. The rules of a simpset are
   172   containing all information about the simpset. The rules of a simpset are
   173   stored in a \emph{discrimination net} (a datastructure for fast
   173   stored in a \emph{discrimination net} (a datastructure for fast
   174   indexing). From this net we can extract the entries using the function @{ML
   174   indexing). From this net we can extract the entries using the function @{ML
   180   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
   180   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
   181   in @{ML_file "Pure/net.ML"}.
   181   in @{ML_file "Pure/net.ML"}.
   182   \end{readmore}
   182   \end{readmore}
   183 
   183 
   184   While antiquotations have many applications, they were originally introduced in order 
   184   While antiquotations have many applications, they were originally introduced in order 
   185   to avoid explicit bindings for theorems such as
   185   to avoid explicit bindings for theorems such as:
   186 *}
   186 *}
   187 
   187 
   188 ML{*val allI = thm "allI" *}
   188 ML{*val allI = thm "allI" *}
   189 
   189 
   190 text {*
   190 text {*
   191   These bindings are difficult to maintain and also can be accidentally
   191   These bindings are difficult to maintain and also can be accidentally
   192   overwritten by the user. This often breakes definitional
   192   overwritten by the user. This often breakes Isabelle
   193   packages. Antiquotations solve this problem, since they are ``linked''
   193   packages. Antiquotations solve this problem, since they are ``linked''
   194   statically at compile-time. However, this static linkage also limits their
   194   statically at compile-time.  However, this static linkage also limits their
   195   usefulness in cases where data needs to be build up dynamically. In the course of 
   195   usefulness in cases where data needs to be build up dynamically. In the
   196   this introduction, we will learn more about
   196   course of this introduction, we will learn more about these antiquotations:
   197   these antiquotations: they greatly simplify Isabelle programming since one
   197   they greatly simplify Isabelle programming since one can directly access all
   198   can directly access all kinds of logical elements from ML.
   198   kinds of logical elements from th ML-level.
   199 
   199 
   200 *}
   200 *}
   201 
   201 
   202 section {* Terms and Types *}
   202 section {* Terms and Types *}
   203 
   203 
   204 text {*
   204 text {*
   205   One way to construct terms of Isabelle on the ML-level is by using the antiquotation 
   205   One way to construct terms of Isabelle on the ML-level is by using the antiquotation 
   206   \mbox{@{text "@{term \<dots>}"}}. For example
   206   \mbox{@{text "@{term \<dots>}"}}. For example:
   207 
   207 
   208   @{ML_response [display,gray] 
   208   @{ML_response [display,gray] 
   209 "@{term \"(a::nat) + b = c\"}" 
   209 "@{term \"(a::nat) + b = c\"}" 
   210 "Const (\"op =\", \<dots>) $ 
   210 "Const (\"op =\", \<dots>) $ 
   211                  (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   211                  (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   229   from what you see at the user level, because the layers of
   229   from what you see at the user level, because the layers of
   230   parsing/type-checking/pretty printing can be quite elaborate. 
   230   parsing/type-checking/pretty printing can be quite elaborate. 
   231 
   231 
   232   \begin{exercise}
   232   \begin{exercise}
   233   Look at the internal term representation of the following terms, and
   233   Look at the internal term representation of the following terms, and
   234   find out why they are represented like this.
   234   find out why they are represented like this:
   235 
   235 
   236   \begin{itemize}
   236   \begin{itemize}
   237   \item @{term "case x of 0 \<Rightarrow> 0 | Suc y \<Rightarrow> y"}  
   237   \item @{term "case x of 0 \<Rightarrow> 0 | Suc y \<Rightarrow> y"}  
   238   \item @{term "\<lambda>(x,y). P y x"}  
   238   \item @{term "\<lambda>(x,y). P y x"}  
   239   \item @{term "{ [x::int] | x. x \<le> -2 }"}  
   239   \item @{term "{ [x::int] | x. x \<le> -2 }"}  
   259   @{ML_response [display,gray] "(@{term \"P x \<Longrightarrow> Q x\"}, @{prop \"P x \<Longrightarrow> Q x\"})" 
   259   @{ML_response [display,gray] "(@{term \"P x \<Longrightarrow> Q x\"}, @{prop \"P x \<Longrightarrow> Q x\"})" 
   260   "(Const (\"==>\", \<dots>) $ \<dots> $ \<dots>, Const (\"==>\", \<dots>) $ \<dots> $ \<dots>)"}
   260   "(Const (\"==>\", \<dots>) $ \<dots> $ \<dots>, Const (\"==>\", \<dots>) $ \<dots> $ \<dots>)"}
   261 
   261 
   262   where it is not (since it is already constructed by a meta-implication). 
   262   where it is not (since it is already constructed by a meta-implication). 
   263 
   263 
   264   Types can be constructed using the antiquotation @{text "@{typ \<dots>}"}. For example
   264   Types can be constructed using the antiquotation @{text "@{typ \<dots>}"}. For example:
   265 
   265 
   266   @{ML_response_fake [display,gray] "@{typ \"bool \<Rightarrow> nat\"}" "bool \<Rightarrow> nat"}
   266   @{ML_response_fake [display,gray] "@{typ \"bool \<Rightarrow> nat\"}" "bool \<Rightarrow> nat"}
   267 
   267 
   268   \begin{readmore}
   268   \begin{readmore}
   269   Types are described in detail in \isccite{sec:types}. Their
   269   Types are described in detail in \isccite{sec:types}. Their
   277 
   277 
   278 text {*
   278 text {*
   279   While antiquotations are very convenient for constructing terms, they can
   279   While antiquotations are very convenient for constructing terms, they can
   280   only construct fixed terms (remember they are ``linked'' at
   280   only construct fixed terms (remember they are ``linked'' at
   281   compile-time). See Recipe~\ref{rec:external} on Page~\pageref{rec:external}
   281   compile-time). See Recipe~\ref{rec:external} on Page~\pageref{rec:external}
   282   for a function that pattern-matches over terms and where the pattern are
   282   for a function that pattern-matches over terms and where the patterns are
   283   constructed from antiquotations.  However, one often needs to construct
   283   constructed using antiquotations.  However, one often needs to construct
   284   terms dynamically. For example, a function that returns the implication
   284   terms dynamically. For example, a function that returns the implication
   285   @{text "\<And>(x::\<tau>). P x \<Longrightarrow> Q x"} taking @{term P}, @{term Q} and the type @{term
   285   @{text "\<And>(x::\<tau>). P x \<Longrightarrow> Q x"} taking @{term P}, @{term Q} and the type @{term
   286   "\<tau>"} as arguments can only be written as
   286   "\<tau>"} as arguments can only be written as:
   287 *}
   287 *}
   288 
   288 
   289 ML{*fun make_imp P Q tau =
   289 ML{*fun make_imp P Q tau =
   290   let
   290   let
   291     val x = Free ("x",tau)
   291     val x = Free ("x",tau)
   292   in 
   292   in 
   293     Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   293     Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   294   end *}
   294   end *}
   295 
   295 
   296 text {*
   296 text {*
   297 
       
   298   The reason is that one cannot pass the arguments @{term P}, @{term Q} and 
   297   The reason is that one cannot pass the arguments @{term P}, @{term Q} and 
   299   @{term "tau"} into an antiquotation. For example the following does \emph{not} work:
   298   @{term "tau"} into an antiquotation. For example the following does \emph{not} work:
   300 *}
   299 *}
   301 
   300 
   302 ML{*fun make_wrong_imp P Q tau = @{prop "\<And>x. P x \<Longrightarrow> Q x"} *}
   301 ML{*fun make_wrong_imp P Q tau = @{prop "\<And>x. P x \<Longrightarrow> Q x"} *}
   355 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *}
   354 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *}
   356 
   355 
   357 text {*
   356 text {*
   358 
   357 
   359   \begin{readmore}
   358   \begin{readmore}
   360   There are many functions in @{ML_file "Pure/logic.ML"} and
   359   There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and
   361   @{ML_file "HOL/hologic.ML"} that make such manual constructions of terms 
   360   @{ML_file "HOL/hologic.ML"} that make such manual constructions of terms 
   362   and types easier.\end{readmore}
   361   and types easier.\end{readmore}
   363 
   362 
   364   Have a look at these files and try to solve the following two exercises:
   363   Have a look at these files and try to solve the following two exercises:
   365 
   364 
   379   Write a function which takes two terms representing natural numbers
   378   Write a function which takes two terms representing natural numbers
   380   in unary notation (like @{term "Suc (Suc (Suc 0))"}), and produce the
   379   in unary notation (like @{term "Suc (Suc (Suc 0))"}), and produce the
   381   number representing their sum.
   380   number representing their sum.
   382   \end{exercise}
   381   \end{exercise}
   383 
   382 
   384 
   383   (FIXME: maybe should go)
   385   (FIXME: operation from page 19 of the implementation manual)
   384 
       
   385 *}
       
   386 
       
   387 ML{*fun nat_to_int t =
       
   388   (case t of
       
   389      @{typ nat} => @{typ int}
       
   390    | Type (s, ts) => Type (s, map nat_to_int ts)
       
   391    | _ => t)*}
       
   392 
       
   393 text {*
       
   394 
       
   395 @{ML_response_fake [display,gray] 
       
   396 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
       
   397 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
       
   398            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
       
   399 
   386 *}
   400 *}
   387 
   401 
   388 section {* Type-Checking *}
   402 section {* Type-Checking *}
   389 
   403 
   390 text {* 
   404 text {* 
   429   \begin{exercise}
   443   \begin{exercise}
   430   Check that the function defined in Exercise~\ref{fun:revsum} returns a
   444   Check that the function defined in Exercise~\ref{fun:revsum} returns a
   431   result that type-checks.
   445   result that type-checks.
   432   \end{exercise}
   446   \end{exercise}
   433 
   447 
   434   (FIXME: @{text "ctyp_of"})
   448   (FIXME: @{text "ctyp_of"}, @{ML fastype_of}, @{text dummyT})
   435 
   449 
   436 *}
   450 *}
   437 
   451 
   438 section {* Theorems *}
   452 section {* Theorems *}
   439 
   453 
   674 *}
   688 *}
   675 
   689 
   676 ML{*val double =
   690 ML{*val double =
   677             (fn x => (x, x))
   691             (fn x => (x, x))
   678         #-> (fn x => fn y => x + y)*}
   692         #-> (fn x => fn y => x + y)*}
       
   693 
       
   694 text {*
   679   
   695   
   680 
       
   681 text {*
       
   682   
       
   683 
       
   684 
       
   685   (FIXME: find a good exercise for combinators)
   696   (FIXME: find a good exercise for combinators)
   686 *}
   697 *}
   687 
   698 
       
   699 
       
   700 (*<*)
       
   701 setup {*
       
   702  Sign.add_consts_i [("bar", @{typ "nat"},NoSyn)] 
       
   703 *}
       
   704 
       
   705 lemma "bar = (1::nat)"
       
   706   oops
       
   707 
       
   708 setup {*   
       
   709   Sign.add_consts_i [("foo", @{typ "nat"},NoSyn)] 
       
   710  #> PureThy.add_defs false [((Binding.name "foo_def", 
       
   711        Logic.mk_equals (Const ("FirstSteps.foo", @{typ "nat"}), @{term "1::nat"})), [])] 
       
   712  #> snd
       
   713 *}
       
   714 
       
   715 lemma "foo = (1::nat)"
       
   716   apply(simp add: foo_def)
       
   717   done
       
   718 
       
   719 thm foo_def
       
   720 (*>*)
       
   721 
   688 end
   722 end