CookBook/FirstSteps.thy
changeset 10 df09e49b19bf
parent 6 007e09485351
child 11 733614e236a3
equal deleted inserted replaced
9:3ddf6c832c61 10:df09e49b19bf
    24 
    24 
    25 chapter {* First Steps *}
    25 chapter {* First Steps *}
    26 
    26 
    27 
    27 
    28 text {* 
    28 text {* 
    29   Isabelle programming is done in Standard ML, however ML-code for Isabelle often
    29   Isabelle programming is done in Standard ML.
    30   includes antiquotations to refer to the logical context of Isabelle. 
       
    31   Just like lemmas and proofs, code in Isabelle is part of a 
    30   Just like lemmas and proofs, code in Isabelle is part of a 
    32   theory. If you want to follow the code written in this chapter, we 
    31   theory. If you want to follow the code written in this chapter, we 
    33   assume you are working inside the theory defined by
    32   assume you are working inside the theory defined by
    34 
    33 
    35   \begin{center}
    34   \begin{center}
    51 
    50 
    52 text {*
    51 text {*
    53   The expression inside \isacommand{ML} commands is immediately evaluated,
    52   The expression inside \isacommand{ML} commands is immediately evaluated,
    54   like ``normal'' Isabelle proof scripts, by using the advance and undo buttons of 
    53   like ``normal'' Isabelle proof scripts, by using the advance and undo buttons of 
    55   your Isabelle environment. The code inside the \isacommand{ML} command 
    54   your Isabelle environment. The code inside the \isacommand{ML} command 
    56   can also contain value- and function bindings, on which the undo operation 
    55   can also contain value- and function bindings. However on such ML-commands the 
    57   does not have any effect. 
    56   undo operation behaves slightly counter-intuitive, because if you define
    58 *}
    57 *}
       
    58 
       
    59 ML {*
       
    60   val foo = true
       
    61 *}
       
    62 
       
    63 text {*
       
    64   then Isabelle's undo operation has no effect on the definition of 
       
    65   @{ML "foo"}. 
       
    66 
       
    67   During coding you might find it necessary to quickly inspect some data
       
    68   in your code. This can be done in a ``quick-and-dirty'' fashion using 
       
    69   @{ML "warning"}. For example
       
    70 *}
       
    71 
       
    72 ML {*
       
    73   val _ = warning "any string"
       
    74 *}
       
    75 
       
    76 text {*
       
    77   will print out the string inside the response buffer of Isabelle.
       
    78 *}
       
    79 
       
    80 
    59 
    81 
    60 section {* Antiquotations *}
    82 section {* Antiquotations *}
    61 
    83 
    62 text {*
    84 text {*
    63   The main advantage of embedding all code in a theory is that the
    85   The main advantage of embedding all code 
    64   code can contain references to entities that are defined on the
    86   in a theory is that the code can contain references to entities defined 
    65   logical level of Isabelle. This is done using antiquotations.
    87   on the logical level of Isabelle. This is done using antiquotations.
    66   For example, one can print out the name of 
    88   For example, one can print out the name of 
    67   the current theory by typing
    89   the current theory by typing
    68 *}
    90 *}
    69 
    91 
    70 ML {* Context.theory_name @{theory} *}
    92 ML {* Context.theory_name @{theory} *}
    73   where @{text "@{theory}"} is an antiquotation that is substituted with the
    95   where @{text "@{theory}"} is an antiquotation that is substituted with the
    74   current theory (remember that we assumed we are inside the theory CookBook). 
    96   current theory (remember that we assumed we are inside the theory CookBook). 
    75   The name of this theory can be extrated using a the function @{ML "Context.theory_name"}. 
    97   The name of this theory can be extrated using a the function @{ML "Context.theory_name"}. 
    76   So the code above returns the string @{ML "\"CookBook\""}.
    98   So the code above returns the string @{ML "\"CookBook\""}.
    77 
    99 
    78   Note that antiquotations are statically scoped, that is the value is
   100   Note, however, that antiquotations are statically scoped, that is the value is
    79   determined at ``compile-time'' not ``run-time''. For example the function
   101   determined at ``compile-time'' not ``run-time''. For example the function
    80 
   102 
    81 *}
   103 *}
    82 
   104 
    83 ML {* 
   105 ML {* 
    91   function is called. Operationally speaking,  @{text "@{theory}"} is 
   113   function is called. Operationally speaking,  @{text "@{theory}"} is 
    92   \emph{not} replaced with code that will look up the current theory in 
   114   \emph{not} replaced with code that will look up the current theory in 
    93   some data structure and return it. Instead, it is literally
   115   some data structure and return it. Instead, it is literally
    94   replaced with the value representing the theory name.
   116   replaced with the value representing the theory name.
    95 
   117 
       
   118   In a similar way you can use antiquotations to refer to types and theorems:
       
   119 *}
       
   120 
       
   121 ML {* @{typ "(int * nat) list"} *}
       
   122 ML {* @{thm allI} *}
       
   123 
       
   124 text {*
    96   In the course of this introduction, we will learn more about 
   125   In the course of this introduction, we will learn more about 
    97   these antoquotations: they greatly simplify Isabelle programming since one
   126   these antoquotations: they greatly simplify Isabelle programming since one
    98   can directly access all kinds of logical elements from ML.
   127   can directly access all kinds of logical elements from ML.
    99 *}
   128 *}
   100 
   129 
   101 section {* Terms *}
   130 section {* Terms *}
   102 
   131 
   103 text {*
   132 text {*
   104   We can simply quote Isabelle terms from ML using the @{text "@{term \<dots>}"} 
   133   Terms of Isabelle can be constructed on the ML-level using the @{text "@{term \<dots>}"} 
   105   antiquotation:
   134   antiquotation:
   106 *}
   135 *}
   107 
   136 
   108 ML {* @{term "(a::nat) + b = c"} *}
   137 ML {* @{term "(a::nat) + b = c"} *}
   109 
   138 
   110 text {*
   139 text {*
   111   This shows the term @{term "(a::nat) + b = c"} in the internal
   140   This will show the term @{term "(a::nat) + b = c"}, but printed out using the internal
   112   representation with all gory details. Terms are just an ML
   141   representation of this term. This internal represenation is just a 
   113   datatype, and they are defined in @{ML_file "Pure/term.ML"}.
   142   datatype defined in @{ML_file "Pure/term.ML"}.
   114   
   143   
   115   The representation of terms uses deBruin indices: bound variables
   144   The internal representation of terms uses the usual deBruin indices mechanism: bound 
   116   are represented by the constructor @{ML Bound}, and the index refers to
   145   variables are represented by the constructor @{ML Bound} whose argument refers to
   117   the number of lambdas we have to skip until we hit the lambda that
   146   the number of Abstractions (@{ML Abs}) we have to skip until we hit the @{ML Abs} that
   118   binds the variable. The names of bound variables are kept at the
   147   binds the corresponding variable. However, the names of bound variables are 
   119   abstractions, but they should be treated just as comments. 
   148   kept at abstractions for printing purposes, and so should be treated just as comments. 
   120   See \ichcite{ch:logic} for more details.
   149   See \ichcite{ch:logic} for more details.
       
   150 
       
   151   (FIXME: Alex why is the reference bolow given. It somehow does not read
       
   152   with what is written above.)
   121 
   153 
   122   \begin{readmore}
   154   \begin{readmore}
   123   Terms are described in detail in \ichcite{ch:logic}. Their
   155   Terms are described in detail in \ichcite{ch:logic}. Their
   124   definition and many useful operations can be found in @{ML_file "Pure/term.ML"}.
   156   definition and many useful operations can be found in @{ML_file "Pure/term.ML"}.
   125   \end{readmore}
   157   \end{readmore}
   126 
   158 
   127   In a similar way we can quote types and theorems:
       
   128 *}
       
   129 
       
   130 ML {* @{typ "(int * nat) list"} *}
       
   131 ML {* @{thm allI} *}
       
   132 
       
   133 text {* 
       
   134   In the default setup, types and theorems are printed as strings. 
       
   135 *}
       
   136 
       
   137 
       
   138 text {*
       
   139   Sometimes the internal representation can be surprisingly different
   159   Sometimes the internal representation can be surprisingly different
   140   from what you see at the user level, because the layer of
   160   from what you see at the user level, because the layer of
   141   parsing/type checking/pretty printing can be quite thick. 
   161   parsing/type checking/pretty printing can be quite elaborate. 
   142 
   162 
   143 \begin{exercise}
   163   \begin{exercise}
   144   Look at the internal term representation of the following terms, and
   164   Look at the internal term representation of the following terms, and
   145   find out why they are represented like this.
   165   find out why they are represented like this.
   146 
   166 
   147   \begin{itemize}
   167   \begin{itemize}
   148   \item @{term "case x of 0 \<Rightarrow> 0 | Suc y \<Rightarrow> y"}  
   168   \item @{term "case x of 0 \<Rightarrow> 0 | Suc y \<Rightarrow> y"}  
   151   \end{itemize}
   171   \end{itemize}
   152 
   172 
   153   Hint: The third term is already quite big, and the pretty printer
   173   Hint: The third term is already quite big, and the pretty printer
   154   may omit parts of it by default. If you want to see all of it, you
   174   may omit parts of it by default. If you want to see all of it, you
   155   can use @{ML "print_depth 50"} to set the limit to a value high enough.
   175   can use @{ML "print_depth 50"} to set the limit to a value high enough.
   156 \end{exercise}
   176   \end{exercise}
   157 *}
   177 
   158 
   178   \begin{exercise}
   159 section {* Type checking *}
   179   Write a function @{ML_text "rev_sum : term -> term"} that takes a
   160 
   180   term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"}
   161 text {* 
   181   and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}.
   162   We can freely construct and manipulate terms, since they are just
   182   Note that @{text "+"} associates to the left.
   163   arbitrary unchecked trees. However, we eventually want to see if a
   183   Try your function on some examples, and see if the result typechecks.
   164   term is wellformed in a certain context.
   184   \end{exercise}
   165 
   185 *}
   166   Type checking is done via @{ML cterm_of}, which turns a @{ML_type
   186 
   167   term} into a  @{ML_type cterm}, a \emph{certified} term. Unlike
   187 text {* FIXME: check possible solution *}
   168   @{ML_type term}s, which are just trees, @{ML_type
   188 
   169   "cterm"}s are abstract objects that are guaranteed to be
   189 ML {* 
   170   type-correct, and can only be constructed via the official
   190   exception FORM_ERROR 
   171   interfaces.
   191 
   172 
   192   fun rev_sum term =
   173   Type
   193     case term of
   174   checking is always relative to a theory context. For now we can use
   194        @{term "op +"} $ (Free (x,t1)) $ (Free (y,t2)) => 
   175   the @{ML "@{theory}"} antiquotation to get hold of the theory at the current
   195                    @{term "op +"} $ (Free (y,t2)) $ (Free (x,t1))
   176   point:
   196     |  @{term "op +"} $ left $ (Free (x,t)) => 
   177 *}
   197                    @{term "op +"} $ (Free (x,t)) $ (rev_sum left)
   178 
   198     |  _ => raise FORM_ERROR
   179 ML {*
   199 *}
   180   let
   200 
   181     val natT = @{typ "nat"}
   201 
   182     val zero = @{term "0::nat"}(*Const ("HOL.zero_class.zero", natT)*)
   202 text {*
   183   in
   203   \begin{exercise}
   184     cterm_of @{theory} 
   204   Write a function which takes two terms representing natural numbers
   185         (Const ("HOL.plus_class.plus", natT --> natT --> natT) 
   205   in unary (like @{term "Suc (Suc (Suc 0))"}), and produce the unary
   186          $ zero $ zero)
   206   number representing their sum.
   187   end
   207   \end{exercise}
       
   208 
       
   209   \begin{exercise}
       
   210   Look at the functions defined in @{ML_file "Pure/logic.ML"} and
       
   211   @{ML_file "HOL/hologic.ML"} and see if they can make your life
       
   212   easier.
       
   213   \end{exercise}
       
   214 
       
   215   (FIXME what is coming next should fit with the main flow)
   188 *}
   216 *}
   189 
   217 
   190 ML {*
   218 ML {*
   191   @{const_name plus}
   219   @{const_name plus}
   192 *}
   220 *}
   202   constants are defined within a type class. Guessing such internal
   230   constants are defined within a type class. Guessing such internal
   203   names can be extremely hard, which is why the system provides
   231   names can be extremely hard, which is why the system provides
   204   another antiquotation: @{ML "@{const_name plus}"} gives just this
   232   another antiquotation: @{ML "@{const_name plus}"} gives just this
   205   name.
   233   name.
   206 
   234 
   207   \begin{exercise}
   235   FIXME: maybe explain @{text "@{prop \<dots>}"} as a special kind of terms 
   208   Write a function @{ML_text "rev_sum : term -> term"} that takes a
   236 *}
   209   term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"}
   237 
   210   and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}.
   238 ML {* @{prop "True"} *}
   211   Note that @{text "+"} associates to the left.
   239 
   212   Try your function on some examples, and see if the result typechecks.
   240 
   213   \end{exercise}
   241 
   214 
   242 
   215   \begin{exercise}
   243 section {* Type checking *}
   216   Write a function which takes two terms representing natural numbers
   244 
   217   in unary (like @{term "Suc (Suc (Suc 0))"}), and produce the unary
   245 text {* 
   218   number representing their sum.
   246   We can freely construct and manipulate terms, since they are just
   219   \end{exercise}
   247   arbitrary unchecked trees. However, we eventually want to see if a
   220 
   248   term is wellformed, or type checks, relative to a theory.
   221   \begin{exercise}
   249 
   222   Look at the functions defined in @{ML_file "Pure/logic.ML"} and
   250   Type checking is done via the function @{ML cterm_of}, which turns 
   223   @{ML_file "HOL/hologic.ML"} and see if they can make your life
   251   a @{ML_type term} into a  @{ML_type cterm}, a \emph{certified} term. 
   224   easier.
   252   Unlike @{ML_type term}s, which are just trees, @{ML_type
   225   \end{exercise}
   253   "cterm"}s are abstract objects that are guaranteed to be
   226 *}
   254   type-correct, and can only be constructed via the official
       
   255   interfaces.
       
   256 
       
   257   (FIXME: Alex what do you mean concretely by ``official interfaces'')
       
   258 
       
   259   Type checking is always relative to a theory context. For now we can use
       
   260   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
       
   261   For example we can write:
       
   262 *}
       
   263 
       
   264 ML {* cterm_of @{theory} @{term "(a::nat) + b = c"} *}
   227 
   265 
   228 section {* Theorems *}
   266 section {* Theorems *}
   229 
   267 
   230 text {*
   268 text {*
   231   Just like @{ML_type cterm}s, theorems (of type @{ML_type thm}) are
   269   Just like @{ML_type cterm}s, theorems (of type @{ML_type thm}) are
   234   basic rules of the Isabelle/Pure logical framework are defined in
   272   basic rules of the Isabelle/Pure logical framework are defined in
   235   @{ML_file "Pure/thm.ML"}. 
   273   @{ML_file "Pure/thm.ML"}. 
   236 
   274 
   237   Using these rules, which are just ML functions, you can do simple
   275   Using these rules, which are just ML functions, you can do simple
   238   natural deduction proofs on the ML level. For example, the statement
   276   natural deduction proofs on the ML level. For example, the statement
   239   @{prop "(\<And>(x::nat). P x \<Longrightarrow> Q x) \<Longrightarrow> P t \<Longrightarrow> Q t"} can be proved like
   277 *}
       
   278 
       
   279   lemma 
       
   280    assumes assm\<^isub>1: "\<And>(x::nat). P x \<Longrightarrow> Q x" 
       
   281    and     assm\<^isub>2: "P t"
       
   282    shows "Q t"
       
   283    (*<*)oops(*>*) 
       
   284 
       
   285 text {*
       
   286   can be proved in ML like 
   240   this\footnote{Note that @{text "|>"} is just reverse
   287   this\footnote{Note that @{text "|>"} is just reverse
   241   application. This combinator, and several variants are defined in
   288   application. This combinator, and several variants are defined in
   242   @{ML_file "Pure/General/basics.ML"}}:
   289   @{ML_file "Pure/General/basics.ML"}}:
       
   290 
       
   291 
       
   292   (FIXME: Alex why did you not use antiquotations for this?)
   243 *}
   293 *}
   244 
   294 
   245 ML {*
   295 ML {*
   246 let
   296 let
   247   val thy = @{theory}
   297   val thy = @{theory}
   268   Qt 
   318   Qt 
   269   |> implies_intr A2
   319   |> implies_intr A2
   270   |> implies_intr A1
   320   |> implies_intr A1
   271 end
   321 end
   272 *}
   322 *}
       
   323 
       
   324 ML {*
       
   325 
       
   326 let
       
   327   val thy = @{theory}
       
   328 
       
   329   val assm1 = cterm_of thy @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"}
       
   330   val assm2 = cterm_of thy @{prop "((P::nat\<Rightarrow>bool) t)"}
       
   331 
       
   332   val Pt_implies_Qt = 
       
   333         assume assm1
       
   334         |> forall_elim (cterm_of thy @{term "t::nat"});
       
   335   
       
   336   val Qt = implies_elim Pt_implies_Qt (assume assm2);
       
   337 in
       
   338 
       
   339   Qt 
       
   340   |> implies_intr assm2
       
   341   |> implies_intr assm1
       
   342 end
       
   343 
       
   344 *}
       
   345 
       
   346 text {*
       
   347   FIXME Explain this program more carefully
       
   348 *}
       
   349 
   273 
   350 
   274 section {* Tactical reasoning *}
   351 section {* Tactical reasoning *}
   275 
   352 
   276 text {*
   353 text {*
   277   The goal-oriented tactical style is similar to the @{text apply}
   354   The goal-oriented tactical style is similar to the @{text apply}