ProgTutorial/General.thy
changeset 345 4c54ef4dc84d
parent 343 8f73e80c8c6f
child 346 0fea8b7a14a1
equal deleted inserted replaced
344:83d5bca38bec 345:4c54ef4dc84d
     3 begin
     3 begin
     4 
     4 
     5 chapter {* Let's Talk About the Good, the Bad and the Ugly *}
     5 chapter {* Let's Talk About the Good, the Bad and the Ugly *}
     6 
     6 
     7 text {*
     7 text {*
     8   Isabelle is build around a few central ideas. One is the LCF-approach to
     8   Isabelle is build around a few central ideas. One central idea is the
     9   theorem proving where there is a small trusted core and everything else is
     9   LCF-approach to theorem proving where there is a small trusted core and
    10   build on top of this trusted core. The central data structures involved
    10   everything else is build on top of this trusted core. The fundamental data
    11   in this core are certified terms and types as well as theorems.
    11   structures involved in this core are certified terms and types, as well as
       
    12   theorems.
    12 *}
    13 *}
    13 
    14 
    14 
    15 
    15 section {* Terms and Types *}
    16 section {* Terms and Types *}
    16 
    17 
    17 text {*
    18 text {*
    18   In Isabelle there are certified terms (respectively types) and uncertified
    19   There are certified terms and uncertified terms (respectively types). 
    19   terms. The latter are called just terms. One way to construct them is by 
    20   Uncertified terms are just called terms. One way to construct them is by 
    20   using the antiquotation \mbox{@{text "@{term \<dots>}"}}. For example
    21   using the antiquotation \mbox{@{text "@{term \<dots>}"}}. For example
    21 
    22 
    22   @{ML_response [display,gray] 
    23   @{ML_response [display,gray] 
    23 "@{term \"(a::nat) + b = c\"}" 
    24 "@{term \"(a::nat) + b = c\"}" 
    24 "Const (\"op =\", \<dots>) $ 
    25 "Const (\"op =\", \<dots>) $ 
    25   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
    26   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
    26 
    27 
    27   will show the term @{term "(a::nat) + b = c"}, but printed using the internal
    28   constructs the term @{term "(a::nat) + b = c"}, but it printed using the internal
    28   representation corresponding to the datatype @{ML_type  "term"} defined as follows: 
    29   representation corresponding to the datatype @{ML_type_ind "term"} defined as follows: 
    29 *}  
    30 *}  
    30 
    31 
    31 ML_val %linenosgray{*datatype term =
    32 ML_val %linenosgray{*datatype term =
    32   Const of string * typ 
    33   Const of string * typ 
    33 | Free of string * typ 
    34 | Free of string * typ 
    35 | Bound of int 
    36 | Bound of int 
    36 | Abs of string * typ * term 
    37 | Abs of string * typ * term 
    37 | $ of term * term *}
    38 | $ of term * term *}
    38 
    39 
    39 text {*
    40 text {*
    40   This datatype implements lambda-terms typed in Church-style.
    41   This datatype implements Church-style lambda-terms, where types are
    41   As can be seen in Line 5, terms use the usual de Bruijn index mechanism
    42   explicitly recorded in the variables, constants and abstractions.  As can be
    42   for representing bound variables.  For
    43   seen in Line 5, terms use the usual de Bruijn index mechanism for
    43   example in
    44   representing bound variables.  For example in
    44 
    45 
    45   @{ML_response_fake [display, gray]
    46   @{ML_response_fake [display, gray]
    46   "@{term \"\<lambda>x y. x y\"}"
    47   "@{term \"\<lambda>x y. x y\"}"
    47   "Abs (\"x\", \"'a \<Rightarrow> 'b\", Abs (\"y\", \"'a\", Bound 1 $ Bound 0))"}
    48   "Abs (\"x\", \"'a \<Rightarrow> 'b\", Abs (\"y\", \"'a\", Bound 1 $ Bound 0))"}
    48 
    49 
    73 
    74 
    74   When constructing terms, you are usually concerned with free variables (as
    75   When constructing terms, you are usually concerned with free variables (as
    75   mentioned earlier, you cannot construct schematic variables using the
    76   mentioned earlier, you cannot construct schematic variables using the
    76   antiquotation @{text "@{term \<dots>}"}). If you deal with theorems, you have to,
    77   antiquotation @{text "@{term \<dots>}"}). If you deal with theorems, you have to,
    77   however, observe the distinction. The reason is that only schematic
    78   however, observe the distinction. The reason is that only schematic
    78   varaibles can be instantiated with terms when a theorem is applied. A
    79   variables can be instantiated with terms when a theorem is applied. A
    79   similar distinction between free and schematic variables holds for types
    80   similar distinction between free and schematic variables holds for types
    80   (see below).
    81   (see below).
    81 
    82 
    82   \begin{readmore}
    83   \begin{readmore}
    83   Terms and types are described in detail in \isccite{sec:terms}. Their
    84   Terms and types are described in detail in \isccite{sec:terms}. Their
    95 
    96 
    96   raises a typing error, while it perfectly ok to construct the term
    97   raises a typing error, while it perfectly ok to construct the term
    97 
    98 
    98   @{ML_response_fake [display,gray] 
    99   @{ML_response_fake [display,gray] 
    99 "let
   100 "let
   100   val omega = Free (\"x\", @{typ nat}) $ Free (\"x\", @{typ nat})
   101   val omega = Free (\"x\", @{typ \"nat \<Rightarrow> nat\"}) $ Free (\"x\", @{typ nat})
   101 in 
   102 in 
   102   tracing (string_of_term @{context} omega)
   103   tracing (string_of_term @{context} omega)
   103 end"
   104 end"
   104   "x x"}
   105   "x x"}
   105 
   106 
   222 "Const \<dots> $ 
   223 "Const \<dots> $ 
   223   Abs (\"x\", \<dots>,
   224   Abs (\"x\", \<dots>,
   224     Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   225     Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   225                 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   226                 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   226 
   227 
   227   There are a number of handy functions that are frequently used for 
   228   There are a number of handy functions that are frequently used for
   228   constructing terms. One is the function @{ML_ind  list_comb}, which takes a term
   229   constructing terms. One is the function @{ML_ind list_comb in Term}, which
   229   and a list of terms as arguments, and produces as output the term
   230   takes a term and a list of terms as arguments, and produces as output the
   230   list applied to the term. For example
   231   term list applied to the term. For example
       
   232 
   231 
   233 
   232 @{ML_response_fake [display,gray]
   234 @{ML_response_fake [display,gray]
   233 "let
   235 "let
   234   val trm = @{term \"P::nat\"}
   236   val trm = @{term \"P::nat\"}
   235   val args = [@{term \"True\"}, @{term \"False\"}]
   237   val args = [@{term \"True\"}, @{term \"False\"}]
   236 in
   238 in
   237   list_comb (trm, args)
   239   list_comb (trm, args)
   238 end"
   240 end"
   239 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"}
   241 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"}
   240 
   242 
   241   Another handy function is @{ML_ind  lambda}, which abstracts a variable 
   243   Another handy function is @{ML_ind lambda in Term}, which abstracts a variable 
   242   in a term. For example
   244   in a term. For example
   243 
   245 
   244   @{ML_response_fake [display,gray]
   246   @{ML_response_fake [display,gray]
   245 "let
   247 "let
   246   val x_nat = @{term \"x::nat\"}
   248   val x_nat = @{term \"x::nat\"}
   269   then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. 
   271   then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. 
   270   This is a fundamental principle
   272   This is a fundamental principle
   271   of Church-style typing, where variables with the same name still differ, if they 
   273   of Church-style typing, where variables with the same name still differ, if they 
   272   have different type.
   274   have different type.
   273 
   275 
   274   There is also the function @{ML_ind  subst_free} with which terms can be
   276   There is also the function @{ML_ind subst_free in Term} with which terms can be
   275   replaced by other terms. For example below, we will replace in @{term
   277   replaced by other terms. For example below, we will replace in @{term
   276   "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by
   278   "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by
   277   @{term y}, and @{term x} by @{term True}.
   279   @{term y}, and @{term x} by @{term True}.
   278 
   280 
   279   @{ML_response_fake [display,gray]
   281   @{ML_response_fake [display,gray]
   296 in
   298 in
   297   subst_free [sub] trm
   299   subst_free [sub] trm
   298 end"
   300 end"
   299   "Free (\"x\", \"nat\")"}
   301   "Free (\"x\", \"nat\")"}
   300 
   302 
   301   Similarly the function @{ML_ind  subst_bounds}, replaces lose bound 
   303   Similarly the function @{ML_ind subst_bounds in Term}, replaces lose bound 
   302   variables with terms. To see how this function works, let us implement a
   304   variables with terms. To see how this function works, let us implement a
   303   function that strips off the outermost quantifiers in a term.
   305   function that strips off the outermost quantifiers in a term.
   304 *}
   306 *}
   305 
   307 
   306 ML{*fun strip_alls (Const ("All", _) $ Abs (n, T, t)) =
   308 ML{*fun strip_alls (Const ("All", _) $ Abs (n, T, t)) =
   307          strip_alls t |>> cons (Free (n, T))
   309                                     strip_alls t |>> cons (Free (n, T))
   308   | strip_alls t = ([], t) *}
   310   | strip_alls t = ([], t) *}
   309 
   311 
   310 text {*
   312 text {*
   311   The function returns a pair consisting of the stripped off variables and
   313   The function returns a pair consisting of the stripped off variables and
   312   the body of the universal quantifications. For example
   314   the body of the universal quantifications. For example
   316 "([Free (\"x\", \"bool\"), Free (\"y\", \"bool\")],
   318 "([Free (\"x\", \"bool\"), Free (\"y\", \"bool\")],
   317   Const (\"op =\", \<dots>) $ Bound 1 $ Bound 0)"}
   319   Const (\"op =\", \<dots>) $ Bound 1 $ Bound 0)"}
   318 
   320 
   319   After calling @{ML strip_alls}, you obtain a term with lose bound variables. With
   321   After calling @{ML strip_alls}, you obtain a term with lose bound variables. With
   320   the function @{ML subst_bounds}, you can replace these lose @{ML_ind 
   322   the function @{ML subst_bounds}, you can replace these lose @{ML_ind 
   321   Bound}s with the stripped off variables.
   323   Bound in Term}s with the stripped off variables.
   322 
   324 
   323   @{ML_response_fake [display, gray, linenos]
   325   @{ML_response_fake [display, gray, linenos]
   324   "let
   326   "let
   325   val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"}
   327   val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"}
   326 in 
   328 in 
   334   returned. The reason is that the head of the list the function @{ML subst_bounds}
   336   returned. The reason is that the head of the list the function @{ML subst_bounds}
   335   takes is the replacement for @{ML "Bound 0"}, the next element for @{ML "Bound 1"}
   337   takes is the replacement for @{ML "Bound 0"}, the next element for @{ML "Bound 1"}
   336   and so on. 
   338   and so on. 
   337 
   339 
   338   There are many convenient functions that construct specific HOL-terms. For
   340   There are many convenient functions that construct specific HOL-terms. For
   339   example @{ML_ind  mk_eq in HOLogic} constructs an equality out of two terms.
   341   example @{ML_ind mk_eq in HOLogic} constructs an equality out of two terms.
   340   The types needed in this equality are calculated from the type of the
   342   The types needed in this equality are calculated from the type of the
   341   arguments. For example
   343   arguments. For example
   342 
   344 
   343 @{ML_response_fake [gray,display]
   345 @{ML_response_fake [gray,display]
   344 "let
   346 "let
   449 
   451 
   450   \footnote{\bf FIXME: Explain the following better; maybe put in a separate
   452   \footnote{\bf FIXME: Explain the following better; maybe put in a separate
   451   section and link with the comment in the antiquotation section.}
   453   section and link with the comment in the antiquotation section.}
   452 
   454 
   453   Occasionally you have to calculate what the ``base'' name of a given
   455   Occasionally you have to calculate what the ``base'' name of a given
   454   constant is. For this you can use the function @{ML_ind  "Sign.extern_const"} or
   456   constant is. For this you can use the function @{ML_ind "Sign.extern_const"} or
   455   @{ML_ind  Long_Name.base_name}. For example:
   457   @{ML_ind  Long_Name.base_name}. For example:
   456 
   458 
   457   @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""}
   459   @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""}
   458 
   460 
   459   The difference between both functions is that @{ML extern_const in Sign} returns
   461   The difference between both functions is that @{ML extern_const in Sign} returns
   472 
   474 
   473 *} 
   475 *} 
   474 
   476 
   475 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *}
   477 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *}
   476 
   478 
   477 text {* This can be equally written with the combinator @{ML_ind  "-->"} as: *}
   479 text {* This can be equally written with the combinator @{ML_ind "-->" in Term} as: *}
   478 
   480 
   479 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *}
   481 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *}
   480 
   482 
   481 text {*
   483 text {*
   482   If you want to construct a function type with more than one argument
   484   If you want to construct a function type with more than one argument
   483   type, then you can use @{ML_ind  "--->"}.
   485   type, then you can use @{ML_ind "--->" in Term}.
   484 *}
   486 *}
   485 
   487 
   486 ML{*fun make_fun_types tys ty = tys ---> ty *}
   488 ML{*fun make_fun_types tys ty = tys ---> ty *}
   487 
   489 
   488 text {*
   490 text {*
   605   where no error is detected.
   607   where no error is detected.
   606 
   608 
   607   Sometimes it is a bit inconvenient to construct a term with 
   609   Sometimes it is a bit inconvenient to construct a term with 
   608   complete typing annotations, especially in cases where the typing 
   610   complete typing annotations, especially in cases where the typing 
   609   information is redundant. A short-cut is to use the ``place-holder'' 
   611   information is redundant. A short-cut is to use the ``place-holder'' 
   610   type @{ML_ind  dummyT} and then let type-inference figure out the 
   612   type @{ML_ind dummyT in Term} and then let type-inference figure out the 
   611   complete type. An example is as follows:
   613   complete type. An example is as follows:
   612 
   614 
   613   @{ML_response_fake [display,gray] 
   615   @{ML_response_fake [display,gray] 
   614 "let
   616 "let
   615   val c = Const (@{const_name \"plus\"}, dummyT) 
   617   val c = Const (@{const_name \"plus\"}, dummyT)