CookBook/FirstSteps.thy
changeset 78 ef778679d3e0
parent 75 f2dea0465bb4
child 81 8fda6b452f28
equal deleted inserted replaced
77:bca83ed1d45a 78:ef778679d3e0
    42   \isacommand{ML}-commands can be evaluated by using the advance and undo buttons of 
    42   \isacommand{ML}-commands can be evaluated by using the advance and undo buttons of 
    43   your Isabelle environment. The code inside the \isacommand{ML}-command 
    43   your Isabelle environment. The code inside the \isacommand{ML}-command 
    44   can also contain value and function bindings, and even those can be
    44   can also contain value and function bindings, and even those can be
    45   undone when the proof script is retracted. As mentioned earlier, we will  
    45   undone when the proof script is retracted. As mentioned earlier, we will  
    46   drop the \isacommand{ML} \isa{\isacharverbatimopen \ldots \isacharverbatimclose} 
    46   drop the \isacommand{ML} \isa{\isacharverbatimopen \ldots \isacharverbatimclose} 
    47   whenever we show code and its response.
    47   whenever we show code.
    48 
    48 
    49   Once a portion of code is relatively stable, one usually wants to 
    49   Once a portion of code is relatively stable, one usually wants to 
    50   export it to a separate ML-file. Such files can then be included in a 
    50   export it to a separate ML-file. Such files can then be included in a 
    51   theory by using \isacommand{uses} in the header of the theory, like
    51   theory by using \isacommand{uses} in the header of the theory, like
    52 
    52 
    78   converting values into strings, namely using the function @{ML makestring}:
    78   converting values into strings, namely using the function @{ML makestring}:
    79 
    79 
    80   @{ML_response_fake [display,gray] "warning (makestring 1)" "\"1\""} 
    80   @{ML_response_fake [display,gray] "warning (makestring 1)" "\"1\""} 
    81 
    81 
    82   However @{ML makestring} only works if the type of what is converted is monomorphic 
    82   However @{ML makestring} only works if the type of what is converted is monomorphic 
    83   and is not a function.
    83   and not a function.
    84 
    84 
    85   The function @{ML "warning"} should only be used for testing purposes, because any
    85   The function @{ML "warning"} should only be used for testing purposes, because any
    86   output this function generates will be overwritten as soon as an error is
    86   output this function generates will be overwritten as soon as an error is
    87   raised. For printing anything more serious and elaborate, the
    87   raised. For printing anything more serious and elaborate, the
    88   function @{ML tracing} is more appropriate. This function writes all output into
    88   function @{ML tracing} is more appropriate. This function writes all output into
    89   a separate tracing buffer. For example
    89   a separate tracing buffer. For example
    90 
    90 
    91   @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""}
    91   @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""}
    92 
    92 
    93   It is also possible to redirect the ``channel'' where the string @{text "foo"} is 
    93   It is also possible to redirect the ``channel'' where the string @{text "foo"} is 
    94   printed to a separate file, e.g. to prevent ProofGeneral from choking on massive 
    94   printed to a separate file, e.g.~to prevent ProofGeneral from choking on massive 
    95   amounts of trace output. This redirection can be achieved using the code
    95   amounts of trace output. This redirection can be achieved using the code
    96 *}
    96 *}
    97 
    97 
    98 ML{*val strip_specials =
    98 ML{*val strip_specials =
    99 let
    99 let
   165   val ({rules,...},_) = MetaSimplifier.rep_ss @{simpset}
   165   val ({rules,...},_) = MetaSimplifier.rep_ss @{simpset}
   166 in
   166 in
   167   map #name (Net.entries rules)
   167   map #name (Net.entries rules)
   168 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   168 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   169 
   169 
   170   The code above extracts the theorem names that are stored in a simpset.
   170   The code above extracts the theorem names that are stored in the current simpset.
   171   We refer to the current simpset with the antiquotation @{text "@{simpset}"}.
   171   We refer to the simpset with the antiquotation @{text "@{simpset}"}.
   172   The function @{ML rep_ss in MetaSimplifier} returns a record
   172   The function @{ML rep_ss in MetaSimplifier} returns a record
   173   containing all information about the simpset. The rules of a simpset are stored
   173   containing all information about the simpset. The rules of a simpset are stored
   174   in a discrimination net (a datastructure for fast indexing). From this net
   174   in a \emph{discrimination net} (a datastructure for fast indexing). From this net
   175   we can extract the entries using the function @{ML Net.entries}.
   175   we can extract the entries using the function @{ML Net.entries}.
   176 
   176 
   177   \begin{readmore}
   177   \begin{readmore}
   178   The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"}
   178   The infrastructure for simpsets is contained in @{ML_file "Pure/meta_simplifier.ML"}
   179   and @{ML_file "Pure/simplifier.ML"}.
   179   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
       
   180   in @{ML_file "Pure/net.ML"}.
   180   \end{readmore}
   181   \end{readmore}
   181 
   182 
   182   While antiquotations have many applications, they were originally introduced in order 
   183   While antiquotations have many applications, they were originally introduced in order 
   183   to avoid explicit bindings for theorems such as
   184   to avoid explicit bindings for theorems such as
   184 *}
   185 *}
   185 
   186 
   186 ML{*val allI = thm "allI" *}
   187 ML{*val allI = thm "allI" *}
   187 
   188 
   188 text {*
   189 text {*
   189   These bindings were difficult to maintain and also could be accidentally
   190   These bindings are difficult to maintain and also can be accidentally
   190   overwritten by the user. This usually broke definitional
   191   overwritten by the user. This often breakes definitional
   191   packages. Antiquotations solve this problem, since they are ``linked''
   192   packages. Antiquotations solve this problem, since they are ``linked''
   192   statically at compile-time. However, this static linkage also limits their
   193   statically at compile-time. However, this static linkage also limits their
   193   usefulness in cases where data needs to be build up dynamically. In the course of 
   194   usefulness in cases where data needs to be build up dynamically. In the course of 
   194   this introduction, we will learn more about
   195   this introduction, we will learn more about
   195   these antiquotations: they greatly simplify Isabelle programming since one
   196   these antiquotations: they greatly simplify Isabelle programming since one
   218   binds the corresponding variable. However, in Isabelle the names of bound variables are 
   219   binds the corresponding variable. However, in Isabelle the names of bound variables are 
   219   kept at abstractions for printing purposes, and so should be treated only as comments. 
   220   kept at abstractions for printing purposes, and so should be treated only as comments. 
   220 
   221 
   221   \begin{readmore}
   222   \begin{readmore}
   222   Terms are described in detail in \isccite{sec:terms}. Their
   223   Terms are described in detail in \isccite{sec:terms}. Their
   223   definition and many useful operations can be found in @{ML_file "Pure/term.ML"}.
   224   definition and many useful operations are implemented in @{ML_file "Pure/term.ML"}.
   224   \end{readmore}
   225   \end{readmore}
   225 
   226 
   226   Sometimes the internal representation of terms can be surprisingly different
   227   Sometimes the internal representation of terms can be surprisingly different
   227   from what you see at the user level, because the layers of
   228   from what you see at the user level, because the layers of
   228   parsing/type-checking/pretty printing can be quite elaborate. 
   229   parsing/type-checking/pretty printing can be quite elaborate. 
   263 
   264 
   264   @{ML_response_fake [display,gray] "@{typ \"bool \<Rightarrow> nat\"}" "bool \<Rightarrow> nat"}
   265   @{ML_response_fake [display,gray] "@{typ \"bool \<Rightarrow> nat\"}" "bool \<Rightarrow> nat"}
   265 
   266 
   266   \begin{readmore}
   267   \begin{readmore}
   267   Types are described in detail in \isccite{sec:types}. Their
   268   Types are described in detail in \isccite{sec:types}. Their
   268   definition and many useful operations can also be found in @{ML_file "Pure/type.ML"}.
   269   definition and many useful operations are implemented 
       
   270   in @{ML_file "Pure/type.ML"}.
   269   \end{readmore}
   271   \end{readmore}
   270 *}
   272 *}
   271 
   273 
   272 
   274 
   273 section {* Constructing Terms and Types Manually *} 
   275 section {* Constructing Terms and Types Manually *} 
   274 
   276 
   275 text {*
   277 text {*
   276 
   278 
   277   While antiquotations are very convenient for constructing terms and types, 
   279   While antiquotations are very convenient for constructing terms, 
   278   they can only construct fixed terms (remember they are ``linked'' at compile-time). 
   280   they can only construct fixed terms (remember they are ``linked'' at compile-time). 
   279   However, one often needs to construct terms
   281   However, one often needs to construct terms
   280   dynamically. For example, a function that returns the implication 
   282   dynamically. For example, a function that returns the implication 
   281   @{text "\<And>(x::\<tau>). P x \<Longrightarrow> Q x"} taking @{term P}, @{term Q} and the type @{term "\<tau>"}
   283   @{text "\<And>(x::\<tau>). P x \<Longrightarrow> Q x"} taking @{term P}, @{term Q} and the type @{term "\<tau>"}
   282   as arguments can only be written as
   284   as arguments can only be written as
   306     "Const \<dots> $ 
   308     "Const \<dots> $ 
   307     Abs (\"x\", Type (\"nat\",[]),
   309     Abs (\"x\", Type (\"nat\",[]),
   308       Const \<dots> $ (Free (\"S\",\<dots>) $ \<dots>) $ 
   310       Const \<dots> $ (Free (\"S\",\<dots>) $ \<dots>) $ 
   309                   (Free (\"T\",\<dots>) $ \<dots>))"}
   311                   (Free (\"T\",\<dots>) $ \<dots>))"}
   310 
   312 
   311   With @{ML make_wrong_imp} we obtain a term involving the @{term "P"} 
   313   Whereas with @{ML make_wrong_imp} we obtain a term involving the @{term "P"} 
   312   and @{text "Q"} from the antiquotation.
   314   and @{text "Q"} from the antiquotation.
   313 
   315 
   314   @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T} @{typ nat}" 
   316   @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T} @{typ nat}" 
   315     "Const \<dots> $ 
   317     "Const \<dots> $ 
   316     Abs (\"x\", \<dots>,
   318     Abs (\"x\", \<dots>,
   335 
   337 
   336   @{ML_response_fake [display,gray] "@{const_name \"Nil\"}" "List.list.Nil"}
   338   @{ML_response_fake [display,gray] "@{const_name \"Nil\"}" "List.list.Nil"}
   337 
   339 
   338   (FIXME: Is it useful to explain @{text "@{const_syntax}"}?)
   340   (FIXME: Is it useful to explain @{text "@{const_syntax}"}?)
   339 
   341 
   340   Similarly, types can be constructed manually. For example a function type
   342   Similarly, one can construct types manually. For example the function returning
   341   can be constructed as follows:
   343   a function type is as follows:
   342 
   344 
   343 *} 
   345 *} 
   344 
   346 
   345 ML{*fun make_fun_type tau1 tau2 = Type ("fun",[tau1,tau2]) *}
   347 ML{*fun make_fun_type tau1 tau2 = Type ("fun",[tau1,tau2]) *}
   346 
   348 
   386   term is well-formed, or type-checks, relative to a theory.
   388   term is well-formed, or type-checks, relative to a theory.
   387   Type-checking is done via the function @{ML cterm_of}, which converts 
   389   Type-checking is done via the function @{ML cterm_of}, which converts 
   388   a @{ML_type term} into a  @{ML_type cterm}, a \emph{certified} term. 
   390   a @{ML_type term} into a  @{ML_type cterm}, a \emph{certified} term. 
   389   Unlike @{ML_type term}s, which are just trees, @{ML_type
   391   Unlike @{ML_type term}s, which are just trees, @{ML_type
   390   "cterm"}s are abstract objects that are guaranteed to be
   392   "cterm"}s are abstract objects that are guaranteed to be
   391   type-correct, and that can only be constructed via the ``official
   393   type-correct, and they can only be constructed via the ``official
   392   interfaces''.
   394   interfaces''.
   393 
   395 
   394   Type-checking is always relative to a theory context. For now we use
   396   Type-checking is always relative to a theory context. For now we use
   395   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
   397   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
   396   For example we can write
   398   For example we can write
   399 
   401 
   400   or use the antiquotation
   402   or use the antiquotation
   401 
   403 
   402   @{ML_response_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"}
   404   @{ML_response_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"}
   403 
   405 
   404   Attempting
   406   Attempting to obtain the certified term for
   405 
   407 
   406   @{ML_response_fake_both [display,gray] "@{cterm \"1 + True\"}" "Type unification failed \<dots>"}
   408   @{ML_response_fake_both [display,gray] "@{cterm \"1 + True\"}" "Type unification failed \<dots>"}
   407 
   409 
   408   yields an error. A slightly more elaborate example is
   410   yields an error (since the term is not typable). A slightly more elaborate
       
   411   example that type-checks is
       
   412 
   409 
   413 
   410 @{ML_response_fake [display,gray] 
   414 @{ML_response_fake [display,gray] 
   411 "let
   415 "let
   412   val natT = @{typ \"nat\"}
   416   val natT = @{typ \"nat\"}
   413   val zero = @{term \"0::nat\"}
   417   val zero = @{term \"0::nat\"}
   425 
   429 
   426 section {* Theorems *}
   430 section {* Theorems *}
   427 
   431 
   428 text {*
   432 text {*
   429   Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} 
   433   Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} 
   430   that can only be built by going through interfaces. As a consequence of this is that
   434   that can only be built by going through interfaces. As a consequence, every proof 
   431   every proof is correct by construction (FIXME reference LCF-philosophy)
   435   in Isabelle is correct by construction (FIXME reference LCF-philosophy)
   432 
   436 
   433   To see theorems in ``action'', let us give a proof for the following statement
   437   To see theorems in ``action'', let us give a proof on the ML-level for the following 
       
   438   statement:
   434 *}
   439 *}
   435 
   440 
   436   lemma 
   441   lemma 
   437    assumes assm\<^isub>1: "\<And>(x::nat). P x \<Longrightarrow> Q x" 
   442    assumes assm\<^isub>1: "\<And>(x::nat). P x \<Longrightarrow> Q x" 
   438    and     assm\<^isub>2: "P t"
   443    and     assm\<^isub>2: "P t"
   439    shows "Q t" (*<*)oops(*>*) 
   444    shows "Q t" (*<*)oops(*>*) 
   440 
   445 
   441 text {*
   446 text {*
   442   on the ML-level:\footnote{Note that @{text "|>"} is reverse
   447   The corresponding ML-code is as follows:\footnote{Note that @{text "|>"} is reverse
   443   application. See Section~\ref{sec:combinators}.}
   448   application. See Section~\ref{sec:combinators}.}
   444 
   449 
   445 @{ML_response_fake [display,gray]
   450 @{ML_response_fake [display,gray]
   446 "let
   451 "let
   447   val thy = @{theory}
   452   val thy = @{theory}
   490 section {* Theorem Attributes *}
   495 section {* Theorem Attributes *}
   491 
   496 
   492 section {* Operations on Constants (Names) *}
   497 section {* Operations on Constants (Names) *}
   493 
   498 
   494 text {*
   499 text {*
   495   (FIXME how can I extract the constant name without the theory name etc)
   500 
       
   501 @{ML_response [display] "Sign.base_name \"List.list.Nil\"" "\"Nil\""}
       
   502   
   496 *}
   503 *}
   497 
   504 
   498 section {* Combinators\label{sec:combinators} *}
   505 section {* Combinators\label{sec:combinators} *}
   499 
   506 
   500 text {*
   507 text {*
   501   Perhaps one of the most puzzling aspects for a beginner when reading at 
   508   Perhaps one of the most puzzling aspects for a beginner when reading  
   502   existing Isabelle code is the liberal use of combinators. At first they 
   509   existing Isabelle code is the liberal use of combinators. At first they 
   503   seem to obstruct the comprehension of the code, but after getting familiar 
   510   seem to obstruct the comprehension of the code, but after getting familiar 
   504   with them they actually ease the reading and also the programming.
   511   with them they actually ease the reading and also the programming.
   505 
   512 
   506   \begin{readmore}
   513   \begin{readmore}
   507   The most frequently used combinator are defined in the files @{ML_file "Pure/library.ML"}
   514   The most frequently used combinator are defined in the files @{ML_file "Pure/library.ML"}
   508   and @{ML_file "Pure/General/basics.ML"}.
   515   and @{ML_file "Pure/General/basics.ML"}.
   509   \end{readmore}
   516   \end{readmore}
   510 
   517 
   511   The simplest combinator is @{ML I} which is just the identidy function.
   518   The simplest combinator is @{ML I} which is just the identity function.
   512 *}
   519 *}
   513 
   520 
   514 ML{*fun I x = x*}
   521 ML{*fun I x = x*}
   515 
   522 
   516 text {* Another frequently used combinator is @{ML K} *}
   523 text {* Another frequently used combinator is @{ML K} *}
   519 
   526 
   520 text {*
   527 text {*
   521   which ``wraps'' a function around the argument @{text "x"}. This function 
   528   which ``wraps'' a function around the argument @{text "x"}. This function 
   522   ignores its argument. 
   529   ignores its argument. 
   523 
   530 
   524   @{ML "(op |>)"}
   531   The next combinator is reverse application defined as 
   525 *}
   532 *}
   526 
   533 
   527 ML{*fun x |> f = f x*}
   534 ML{*fun x |> f = f x*}
   528 
   535 
       
   536 text {* The purpose of this combinator is to implement functions in a  
       
   537   ``waterfall fashion''. Consider for example the function *}
       
   538 
       
   539 ML %linenumbers{*fun inc_by_five x =
       
   540   x |> (fn x => x + 1)
       
   541     |> (fn x => (x, x))
       
   542     |> fst
       
   543     |> (fn x => x + 4)*}
       
   544 
       
   545 text {*
       
   546   which increments the argument @{text x} by 5. It does this by first incrementing 
       
   547   the argument by 1 (Line 2); then storing the result in a pair (Line 3); taking 
       
   548   the first component of the pair (Line 4) and finally incrementing the first 
       
   549   component by 4 (Line 5). This kind of cascading manipulations of values is quite
       
   550   common when extending theories (for example by adding a definition, followed by
       
   551   lemmas and so on). Writing the function @{ML inc_by_five} using the reverse
       
   552   application is much clearer than writing
       
   553 *}
       
   554 
       
   555 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*}
       
   556 
       
   557 text {* or *}
       
   558 
       
   559 ML{*fun inc_by_five x = 
       
   560        ((fn x => x + 4) o fst o (fn x => (x, x)) o (fn x => x + 1)) x*}
       
   561 
       
   562 text {* and much more economical than *}
       
   563 
       
   564 ML{*fun inc_by_five x =
       
   565    let val y1 = x + 1
       
   566        val y2 = (y1, y1)
       
   567        val y3 = fst y2
       
   568        val y4 = y3 + 4
       
   569    in y4 end*}
       
   570 
       
   571 text {* 
       
   572   Similarly, the combinator @{ML "(op #>)"} is the reverse function 
       
   573   composition. It allows us to define functions as follows
       
   574 *}
       
   575 
       
   576 ML{*val inc_by_six = 
       
   577       (fn x => x + 1)
       
   578    #> (fn x => x + 2)
       
   579    #> (fn x => x + 3)*}
       
   580 
       
   581 text {* 
       
   582   which is the function composed of first the increment-by-one function and then
       
   583   increment-by-two, followed by increment-by-three. Applying 6 to this function 
       
   584   yields
       
   585 
       
   586   @{ML_response [display,gray] "inc_by_six 6" "12"}
       
   587 
       
   588   as expected.
       
   589 
       
   590   The remaining combinators add convenience for the ``waterfall method''
       
   591   of writing functions. The combinator @{ML tap} allows one to get 
       
   592   hold of a intermediate result for some side-calculations. For
       
   593   example the function *}
       
   594 
       
   595 ML{*fun inc_by_three x =
       
   596      x |> (fn x => x + 1)
       
   597        |> tap (fn x => tracing (makestring x))
       
   598        |> (fn x => x + 2)*}
       
   599 
       
   600 text {* increments the argument first by one and then by two. In the middle,
       
   601   however, it prints the ``plus-one'' intermediate result inside the
       
   602   tracing buffer.
       
   603 
       
   604   The combinator @{ML "(op `)"} is similar, but applies a function to the value
       
   605   and returns the result together with the original value as pair. For example
       
   606   the following function takes @{text x} then increments @{text x} and returns
       
   607   the pair @{ML "(x + 1,x)" for x}. It then increments the right-hand component 
       
   608   of the pair.
       
   609 *}
       
   610 
       
   611 ML{*fun inc_as_pair x =
       
   612      x |> `(fn x => x + 1)
       
   613        |> (fn (x, y) => (x, y + 1))*}
       
   614 
       
   615 text {*
       
   616   The combinators @{ML "(op |>>)"} and @{ML "(op ||>)"} are defined for 
       
   617   functions manipulating pairs. The first applies the function to
       
   618   the first component of the pair:
       
   619 *}
       
   620 
       
   621 ML{*fun (x, y) |>> f = (f x, y)*}
       
   622 
       
   623 text {*
       
   624   and the second combinator to the second component:
       
   625 *}
       
   626 
       
   627 ML{*fun (x, y) ||> f = (x, f y)*}
       
   628 
       
   629 
   529 end
   630 end