ProgTutorial/Essential.thy
changeset 517 d8c376662bb4
parent 513 f223f8223d4a
child 529 13d7ea419c5f
equal deleted inserted replaced
516:fb6c29a90003 517:d8c376662bb4
     1 theory Essential
     1 theory Essential
     2 imports Base First_Steps
     2 imports Base First_Steps
     3 begin
     3 begin
     4 
       
     5 (*<*)
       
     6 setup{*
       
     7 open_file_with_prelude 
       
     8   "Essential_Code.thy"
       
     9   ["theory Essential", "imports Base First_Steps", "begin"]
       
    10 *}
       
    11 (*>*)
       
    12 
       
    13 
     4 
    14 chapter {* Isabelle Essentials *}
     5 chapter {* Isabelle Essentials *}
    15 
     6 
    16 text {*
     7 text {*
    17    \begin{flushright}
     8    \begin{flushright}
   227   function below we mimic the behaviour of the usual pretty printer for
   218   function below we mimic the behaviour of the usual pretty printer for
   228   datatypes (it uses pretty-printing functions which will be explained in more
   219   datatypes (it uses pretty-printing functions which will be explained in more
   229   detail in Section~\ref{sec:pretty}).
   220   detail in Section~\ref{sec:pretty}).
   230 *}
   221 *}
   231 
   222 
   232 ML{*local
   223 ML %grayML{*local
   233   fun pp_pair (x, y) = Pretty.list "(" ")" [x, y]
   224   fun pp_pair (x, y) = Pretty.list "(" ")" [x, y]
   234   fun pp_list xs = Pretty.list "[" "]" xs
   225   fun pp_list xs = Pretty.list "[" "]" xs
   235   fun pp_str s   = Pretty.str s
   226   fun pp_str s   = Pretty.str s
   236   fun pp_qstr s  = Pretty.quote (pp_str s)
   227   fun pp_qstr s  = Pretty.quote (pp_str s)
   237   fun pp_int i   = pp_str (string_of_int i)
   228   fun pp_int i   = pp_str (string_of_int i)
   249 text {*
   240 text {*
   250   We can install this pretty printer with the function 
   241   We can install this pretty printer with the function 
   251   @{ML_ind addPrettyPrinter in PolyML} as follows.
   242   @{ML_ind addPrettyPrinter in PolyML} as follows.
   252 *}
   243 *}
   253 
   244 
   254 ML{*PolyML.addPrettyPrinter 
   245 ML %grayML{*PolyML.addPrettyPrinter 
   255   (fn _ => fn _ => ml_pretty o Pretty.to_ML o raw_pp_typ)*}
   246   (fn _ => fn _ => ml_pretty o Pretty.to_ML o raw_pp_typ)*}
   256 
   247 
   257 text {*
   248 text {*
   258   Now the type bool is printed out in full detail.
   249   Now the type bool is printed out in full detail.
   259 
   250 
   279 
   270 
   280   We can restore the usual behaviour of Isabelle's pretty printer
   271   We can restore the usual behaviour of Isabelle's pretty printer
   281   with the code
   272   with the code
   282 *}
   273 *}
   283 
   274 
   284 ML{*PolyML.addPrettyPrinter 
   275 ML %grayML{*PolyML.addPrettyPrinter 
   285   (fn _ => fn _ => ml_pretty o Pretty.to_ML o Proof_Display.pp_typ Pure.thy)*}
   276   (fn _ => fn _ => ml_pretty o Pretty.to_ML o Proof_Display.pp_typ Pure.thy)*}
   286 
   277 
   287 text {*
   278 text {*
   288   After that the types for booleans, lists and so on are printed out again 
   279   After that the types for booleans, lists and so on are printed out again 
   289   the standard Isabelle way.
   280   the standard Isabelle way.
   310   function that returns the implication @{text "\<And>(x::nat). P x \<Longrightarrow> Q x"} taking
   301   function that returns the implication @{text "\<And>(x::nat). P x \<Longrightarrow> Q x"} taking
   311   @{term P} and @{term Q} as arguments can only be written as:
   302   @{term P} and @{term Q} as arguments can only be written as:
   312 
   303 
   313 *}
   304 *}
   314 
   305 
   315 ML{*fun make_imp P Q =
   306 ML %grayML{*fun make_imp P Q =
   316 let
   307 let
   317   val x = Free ("x", @{typ nat})
   308   val x = Free ("x", @{typ nat})
   318 in 
   309 in 
   319   Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   310   Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   320 end *}
   311 end *}
   323   The reason is that you cannot pass the arguments @{term P} and @{term Q} 
   314   The reason is that you cannot pass the arguments @{term P} and @{term Q} 
   324   into an antiquotation.\footnote{At least not at the moment.} For example 
   315   into an antiquotation.\footnote{At least not at the moment.} For example 
   325   the following does \emph{not} work.
   316   the following does \emph{not} work.
   326 *}
   317 *}
   327 
   318 
   328 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *}
   319 ML %grayML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *}
   329 
   320 
   330 text {*
   321 text {*
   331   To see this, apply @{text "@{term S}"} and @{text "@{term T}"} 
   322   To see this, apply @{text "@{term S}"} and @{text "@{term T}"} 
   332   to both functions. With @{ML make_imp} you obtain the intended term involving 
   323   to both functions. With @{ML make_imp} you obtain the intended term involving 
   333   the given arguments
   324   the given arguments
   425   Similarly the function @{ML_ind subst_bounds in Term}, replaces lose bound 
   416   Similarly the function @{ML_ind subst_bounds in Term}, replaces lose bound 
   426   variables with terms. To see how this function works, let us implement a
   417   variables with terms. To see how this function works, let us implement a
   427   function that strips off the outermost forall quantifiers in a term.
   418   function that strips off the outermost forall quantifiers in a term.
   428 *}
   419 *}
   429 
   420 
   430 ML{*fun strip_alls t =
   421 ML %grayML{*fun strip_alls t =
   431 let 
   422 let 
   432   fun aux (x, T, t) = strip_alls t |>> cons (Free (x, T))
   423   fun aux (x, T, t) = strip_alls t |>> cons (Free (x, T))
   433 in
   424 in
   434   case t of
   425   case t of
   435     Const (@{const_name All}, _) $ Abs body => aux body
   426     Const (@{const_name All}, _) $ Abs body => aux body
   448   Note that we produced in the body two dangling de Bruijn indices. 
   439   Note that we produced in the body two dangling de Bruijn indices. 
   449   Later on we will also use the inverse function that
   440   Later on we will also use the inverse function that
   450   builds the quantification from a body and a list of (free) variables.
   441   builds the quantification from a body and a list of (free) variables.
   451 *}
   442 *}
   452   
   443   
   453 ML{*fun build_alls ([], t) = t
   444 ML %grayML{*fun build_alls ([], t) = t
   454   | build_alls (Free (x, T) :: vs, t) = 
   445   | build_alls (Free (x, T) :: vs, t) = 
   455       Const (@{const_name "All"}, (T --> @{typ bool}) --> @{typ bool}) 
   446       Const (@{const_name "All"}, (T --> @{typ bool}) --> @{typ bool}) 
   456         $ Abs (x, T, build_alls (vs, t))*}
   447         $ Abs (x, T, build_alls (vs, t))*}
   457 
   448 
   458 text {*
   449 text {*
   547   constants. They usually crop up when pattern matching terms or types, or
   538   constants. They usually crop up when pattern matching terms or types, or
   548   when constructing them. While it is perfectly ok to write the function
   539   when constructing them. While it is perfectly ok to write the function
   549   @{text is_true} as follows
   540   @{text is_true} as follows
   550 *}
   541 *}
   551 
   542 
   552 ML{*fun is_true @{term True} = true
   543 ML %grayML{*fun is_true @{term True} = true
   553   | is_true _ = false*}
   544   | is_true _ = false*}
   554 
   545 
   555 text {*
   546 text {*
   556   this does not work for picking out @{text "\<forall>"}-quantified terms. Because
   547   this does not work for picking out @{text "\<forall>"}-quantified terms. Because
   557   the function 
   548   the function 
   558 *}
   549 *}
   559 
   550 
   560 ML{*fun is_all (@{term All} $ _) = true
   551 ML %grayML{*fun is_all (@{term All} $ _) = true
   561   | is_all _ = false*}
   552   | is_all _ = false*}
   562 
   553 
   563 text {* 
   554 text {* 
   564   will not correctly match the formula @{prop[source] "\<forall>x::nat. P x"}: 
   555   will not correctly match the formula @{prop[source] "\<forall>x::nat. P x"}: 
   565 
   556 
   569   fixes the type of the constant @{term "All"} to be @{typ "('a \<Rightarrow> bool) \<Rightarrow> bool"} for 
   560   fixes the type of the constant @{term "All"} to be @{typ "('a \<Rightarrow> bool) \<Rightarrow> bool"} for 
   570   an arbitrary, but fixed type @{typ "'a"}. A properly working alternative 
   561   an arbitrary, but fixed type @{typ "'a"}. A properly working alternative 
   571   for this function is
   562   for this function is
   572 *}
   563 *}
   573 
   564 
   574 ML{*fun is_all (Const ("HOL.All", _) $ _) = true
   565 ML %grayML{*fun is_all (Const ("HOL.All", _) $ _) = true
   575   | is_all _ = false*}
   566   | is_all _ = false*}
   576 
   567 
   577 text {* 
   568 text {* 
   578   because now
   569   because now
   579 
   570 
   584 
   575 
   585   However there is still a problem: consider the similar function that
   576   However there is still a problem: consider the similar function that
   586   attempts to pick out @{text "Nil"}-terms:
   577   attempts to pick out @{text "Nil"}-terms:
   587 *}
   578 *}
   588 
   579 
   589 ML{*fun is_nil (Const ("Nil", _)) = true
   580 ML %grayML{*fun is_nil (Const ("Nil", _)) = true
   590   | is_nil _ = false *}
   581   | is_nil _ = false *}
   591 
   582 
   592 text {* 
   583 text {* 
   593   Unfortunately, also this function does \emph{not} work as expected, since
   584   Unfortunately, also this function does \emph{not} work as expected, since
   594 
   585 
   620   variable parts of the constant's name. Therefore a function for 
   611   variable parts of the constant's name. Therefore a function for 
   621   matching against constants that have a polymorphic type should 
   612   matching against constants that have a polymorphic type should 
   622   be written as follows.
   613   be written as follows.
   623 *}
   614 *}
   624 
   615 
   625 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true
   616 ML %grayML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true
   626   | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true
   617   | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true
   627   | is_nil_or_all _ = false *}
   618   | is_nil_or_all _ = false *}
   628 
   619 
   629 text {*
   620 text {*
   630   The antiquotation for properly referencing type constants is @{text "@{type_name \<dots>}"}.
   621   The antiquotation for properly referencing type constants is @{text "@{type_name \<dots>}"}.
   638   when defining constants. For example the function returning a function 
   629   when defining constants. For example the function returning a function 
   639   type is as follows:
   630   type is as follows:
   640 
   631 
   641 *} 
   632 *} 
   642 
   633 
   643 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *}
   634 ML %grayML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *}
   644 
   635 
   645 text {* This can be equally written with the combinator @{ML_ind "-->" in Term} as: *}
   636 text {* This can be equally written with the combinator @{ML_ind "-->" in Term} as: *}
   646 
   637 
   647 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *}
   638 ML %grayML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *}
   648 
   639 
   649 text {*
   640 text {*
   650   If you want to construct a function type with more than one argument
   641   If you want to construct a function type with more than one argument
   651   type, then you can use @{ML_ind "--->" in Term}.
   642   type, then you can use @{ML_ind "--->" in Term}.
   652 *}
   643 *}
   653 
   644 
   654 ML{*fun make_fun_types tys ty = tys ---> ty *}
   645 ML %grayML{*fun make_fun_types tys ty = tys ---> ty *}
   655 
   646 
   656 text {*
   647 text {*
   657   A handy function for manipulating terms is @{ML_ind map_types in Term}: it takes a 
   648   A handy function for manipulating terms is @{ML_ind map_types in Term}: it takes a 
   658   function and applies it to every type in a term. You can, for example,
   649   function and applies it to every type in a term. You can, for example,
   659   change every @{typ nat} in a term into an @{typ int} using the function:
   650   change every @{typ nat} in a term into an @{typ int} using the function:
   660 *}
   651 *}
   661 
   652 
   662 ML{*fun nat_to_int ty =
   653 ML %grayML{*fun nat_to_int ty =
   663   (case ty of
   654   (case ty of
   664      @{typ nat} => @{typ int}
   655      @{typ nat} => @{typ int}
   665    | Type (s, tys) => Type (s, map nat_to_int tys)
   656    | Type (s, tys) => Type (s, map nat_to_int tys)
   666    | _ => ty)*}
   657    | _ => ty)*}
   667 
   658 
   800 
   791 
   801 text_raw {*
   792 text_raw {*
   802   \begin{figure}[t]
   793   \begin{figure}[t]
   803   \begin{minipage}{\textwidth}
   794   \begin{minipage}{\textwidth}
   804   \begin{isabelle}*}
   795   \begin{isabelle}*}
   805 ML{*fun pretty_helper aux env =
   796 ML %grayML{*fun pretty_helper aux env =
   806   env |> Vartab.dest  
   797   env |> Vartab.dest  
   807       |> map aux
   798       |> map aux
   808       |> map (fn (s1, s2) => Pretty.block [s1, Pretty.str " := ", s2]) 
   799       |> map (fn (s1, s2) => Pretty.block [s1, Pretty.str " := ", s2]) 
   809       |> Pretty.enum "," "[" "]" 
   800       |> Pretty.enum "," "[" "]" 
   810       |> pwriteln
   801       |> pwriteln
   862 *}
   853 *}
   863 
   854 
   864 class s1
   855 class s1
   865 class s2 
   856 class s2 
   866 
   857 
   867 ML{*val (tyenv, index) = let
   858 ML %grayML{*val (tyenv, index) = let
   868   val ty1 = @{typ_pat "?'a::s1"}
   859   val ty1 = @{typ_pat "?'a::s1"}
   869   val ty2 = @{typ_pat "?'b::s2"}
   860   val ty2 = @{typ_pat "?'b::s2"}
   870 in
   861 in
   871   Sign.typ_unify @{theory} (ty1, ty2) (Vartab.empty, 0) 
   862   Sign.typ_unify @{theory} (ty1, ty2) (Vartab.empty, 0) 
   872 end*}
   863 end*}
   914   also from the structure @{ML_struct Sign}. This function returns a @{ML_type
   905   also from the structure @{ML_struct Sign}. This function returns a @{ML_type
   915   Type.tyenv} as well, but might raise the exception @{text TYPE_MATCH} in case
   906   Type.tyenv} as well, but might raise the exception @{text TYPE_MATCH} in case
   916   of failure. For example
   907   of failure. For example
   917 *}
   908 *}
   918 
   909 
   919 ML{*val tyenv_match = let
   910 ML %grayML{*val tyenv_match = let
   920   val pat = @{typ_pat "?'a * ?'b"}
   911   val pat = @{typ_pat "?'a * ?'b"}
   921   and ty  = @{typ_pat "bool list * nat"}
   912   and ty  = @{typ_pat "bool list * nat"}
   922 in
   913 in
   923   Sign.typ_match @{theory} (pat, ty) Vartab.empty 
   914   Sign.typ_match @{theory} (pat, ty) Vartab.empty 
   924 end*}
   915 end*}
   942   @{ML subst_type in Envir} for matchers and @{ML norm_type in Envir} 
   933   @{ML subst_type in Envir} for matchers and @{ML norm_type in Envir} 
   943   for unifiers. To show the difference, let us calculate the 
   934   for unifiers. To show the difference, let us calculate the 
   944   following matcher:
   935   following matcher:
   945 *}
   936 *}
   946 
   937 
   947 ML{*val tyenv_match' = let
   938 ML %grayML{*val tyenv_match' = let
   948   val pat = @{typ_pat "?'a * ?'b"}
   939   val pat = @{typ_pat "?'a * ?'b"}
   949   and ty  = @{typ_pat "?'b list * nat"}
   940   and ty  = @{typ_pat "?'b list * nat"}
   950 in
   941 in
   951   Sign.typ_match @{theory} (pat, ty) Vartab.empty 
   942   Sign.typ_match @{theory} (pat, ty) Vartab.empty 
   952 end*}
   943 end*}
   987   first_order_match in Pattern} for terms.  This matching function returns a
   978   first_order_match in Pattern} for terms.  This matching function returns a
   988   type environment and a term environment.  To pretty print the latter we use
   979   type environment and a term environment.  To pretty print the latter we use
   989   the function @{text "pretty_env"}:
   980   the function @{text "pretty_env"}:
   990 *}
   981 *}
   991 
   982 
   992 ML{*fun pretty_env ctxt env =
   983 ML %grayML{*fun pretty_env ctxt env =
   993 let
   984 let
   994   fun get_trms (v, (T, t)) = (Var (v, T), t) 
   985   fun get_trms (v, (T, t)) = (Var (v, T), t) 
   995   val print = pairself (pretty_term ctxt)
   986   val print = pairself (pretty_term ctxt)
   996 in
   987 in
   997   pretty_helper (print o get_trms) env 
   988   pretty_helper (print o get_trms) env 
  1002   a schematic term variable with a type and a term.  An example of a first-order 
   993   a schematic term variable with a type and a term.  An example of a first-order 
  1003   matching problem is the term @{term "P (\<lambda>a b. Q b a)"} and the pattern 
   994   matching problem is the term @{term "P (\<lambda>a b. Q b a)"} and the pattern 
  1004   @{text "?X ?Y"}.
   995   @{text "?X ?Y"}.
  1005 *}
   996 *}
  1006 
   997 
  1007 ML{*val (_, fo_env) = let
   998 ML %grayML{*val (_, fo_env) = let
  1008   val fo_pat = @{term_pat "(?X::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool) ?Y"}
   999   val fo_pat = @{term_pat "(?X::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool) ?Y"}
  1009   val trm_a = @{term "P::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool"} 
  1000   val trm_a = @{term "P::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool"} 
  1010   val trm_b = @{term "\<lambda>a b. (Q::nat\<Rightarrow>nat\<Rightarrow>nat) b a"}
  1001   val trm_b = @{term "\<lambda>a b. (Q::nat\<Rightarrow>nat\<Rightarrow>nat) b a"}
  1011   val init = (Vartab.empty, Vartab.empty) 
  1002   val init = (Vartab.empty, Vartab.empty) 
  1012 in
  1003 in
  1121   not posses a single most general solution. Therefore Isabelle implements the
  1112   not posses a single most general solution. Therefore Isabelle implements the
  1122   unification function @{ML_ind unifiers in Unify} so that it returns a lazy
  1113   unification function @{ML_ind unifiers in Unify} so that it returns a lazy
  1123   list of potentially infinite unifiers.  An example is as follows
  1114   list of potentially infinite unifiers.  An example is as follows
  1124 *}
  1115 *}
  1125 
  1116 
  1126 ML{*val uni_seq =
  1117 ML %grayML{*val uni_seq =
  1127 let 
  1118 let 
  1128   val trm1 = @{term_pat "?X ?Y"}
  1119   val trm1 = @{term_pat "?X ?Y"}
  1129   val trm2 = @{term "f a"}
  1120   val trm2 = @{term "f a"}
  1130   val init = Envir.empty 0
  1121   val init = Envir.empty 0
  1131 in
  1122 in
  1136   The unifiers can be extracted from the lazy sequence using the 
  1127   The unifiers can be extracted from the lazy sequence using the 
  1137   function @{ML_ind "Seq.pull"}. In the example we obtain three 
  1128   function @{ML_ind "Seq.pull"}. In the example we obtain three 
  1138   unifiers @{text "un1\<dots>un3"}.
  1129   unifiers @{text "un1\<dots>un3"}.
  1139 *}
  1130 *}
  1140 
  1131 
  1141 ML{*val SOME ((un1, _), next1) = Seq.pull uni_seq;
  1132 ML %grayML{*val SOME ((un1, _), next1) = Seq.pull uni_seq;
  1142 val SOME ((un2, _), next2) = Seq.pull next1;
  1133 val SOME ((un2, _), next2) = Seq.pull next1;
  1143 val SOME ((un3, _), next3) = Seq.pull next2;
  1134 val SOME ((un3, _), next3) = Seq.pull next2;
  1144 val NONE = Seq.pull next3 *}
  1135 val NONE = Seq.pull next3 *}
  1145 
  1136 
  1146 text {*
  1137 text {*
  1224   from an environment the corresponding variable mappings for schematic type 
  1215   from an environment the corresponding variable mappings for schematic type 
  1225   and term variables. These mappings can be turned into proper 
  1216   and term variables. These mappings can be turned into proper 
  1226   @{ML_type ctyp}-pairs with the function
  1217   @{ML_type ctyp}-pairs with the function
  1227 *}
  1218 *}
  1228 
  1219 
  1229 ML{*fun prep_trm thy (x, (T, t)) = 
  1220 ML %grayML{*fun prep_trm thy (x, (T, t)) = 
  1230   (cterm_of thy (Var (x, T)), cterm_of thy t)*} 
  1221   (cterm_of thy (Var (x, T)), cterm_of thy t)*} 
  1231 
  1222 
  1232 text {*
  1223 text {*
  1233   and into proper @{ML_type cterm}-pairs with
  1224   and into proper @{ML_type cterm}-pairs with
  1234 *}
  1225 *}
  1235 
  1226 
  1236 ML{*fun prep_ty thy (x, (S, ty)) = 
  1227 ML %grayML{*fun prep_ty thy (x, (S, ty)) = 
  1237   (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)*}
  1228   (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)*}
  1238 
  1229 
  1239 text {*
  1230 text {*
  1240   We can now calculate the instantiations from the matching function. 
  1231   We can now calculate the instantiations from the matching function. 
  1241 *}
  1232 *}
  1626   also implements a mechanism where a theorem name can refer to a custom theorem 
  1617   also implements a mechanism where a theorem name can refer to a custom theorem 
  1627   list. For this you can use the function @{ML_ind add_thms_dynamic in Global_Theory}. 
  1618   list. For this you can use the function @{ML_ind add_thms_dynamic in Global_Theory}. 
  1628   To see how it works let us assume we defined our own theorem list @{text MyThmList}.
  1619   To see how it works let us assume we defined our own theorem list @{text MyThmList}.
  1629 *}
  1620 *}
  1630 
  1621 
  1631 ML{*structure MyThmList = Generic_Data
  1622 ML %grayML{*structure MyThmList = Generic_Data
  1632   (type T = thm list
  1623   (type T = thm list
  1633    val empty = []
  1624    val empty = []
  1634    val extend = I
  1625    val extend = I
  1635    val merge = merge Thm.eq_thm_prop)
  1626    val merge = merge Thm.eq_thm_prop)
  1636 
  1627 
  1807   @{text "?list"}. For this we can use the function 
  1798   @{text "?list"}. For this we can use the function 
  1808   @{ML_ind forall_intr_vars in Drule}. This allows us to implement the
  1799   @{ML_ind forall_intr_vars in Drule}. This allows us to implement the
  1809   following function for atomizing a theorem.
  1800   following function for atomizing a theorem.
  1810 *}
  1801 *}
  1811 
  1802 
  1812 ML{*fun atomize_thm thm =
  1803 ML %grayML{*fun atomize_thm thm =
  1813 let
  1804 let
  1814   val thm' = forall_intr_vars thm
  1805   val thm' = forall_intr_vars thm
  1815   val thm'' = Object_Logic.atomize (cprop_of thm')
  1806   val thm'' = Object_Logic.atomize (cprop_of thm')
  1816 in
  1807 in
  1817   Raw_Simplifier.rewrite_rule [thm''] thm'
  1808   Raw_Simplifier.rewrite_rule [thm''] thm'
  1848   There is also the possibility of proving multiple goals at the same time
  1839   There is also the possibility of proving multiple goals at the same time
  1849   using the function @{ML_ind prove_multi in Goal}. For this let us define the
  1840   using the function @{ML_ind prove_multi in Goal}. For this let us define the
  1850   following three helper functions.
  1841   following three helper functions.
  1851 *}
  1842 *}
  1852 
  1843 
  1853 ML{*fun rep_goals i = replicate i @{prop "f x = f x"}
  1844 ML %grayML{*fun rep_goals i = replicate i @{prop "f x = f x"}
  1854 fun rep_tacs i = replicate i (rtac @{thm refl})
  1845 fun rep_tacs i = replicate i (rtac @{thm refl})
  1855 
  1846 
  1856 fun multi_test ctxt i =
  1847 fun multi_test ctxt i =
  1857   Goal.prove_multi ctxt ["f", "x"] [] (rep_goals i) 
  1848   Goal.prove_multi ctxt ["f", "x"] [] (rep_goals i) 
  1858     (K ((Goal.conjunction_tac THEN' RANGE (rep_tacs i)) 1))*}
  1849     (K ((Goal.conjunction_tac THEN' RANGE (rep_tacs i)) 1))*}
  1869   large goals. If you increase the counter in the code above to @{text 3000}, 
  1860   large goals. If you increase the counter in the code above to @{text 3000}, 
  1870   you will notice that takes approximately ten(!) times longer than
  1861   you will notice that takes approximately ten(!) times longer than
  1871   using @{ML map} and @{ML prove in Goal}.
  1862   using @{ML map} and @{ML prove in Goal}.
  1872 *}
  1863 *}
  1873   
  1864   
  1874 ML{*let 
  1865 ML %grayML{*let 
  1875   fun test_prove ctxt thm =
  1866   fun test_prove ctxt thm =
  1876     Goal.prove ctxt ["P", "x"] [] thm (K (rtac @{thm refl} 1))
  1867     Goal.prove ctxt ["P", "x"] [] thm (K (rtac @{thm refl} 1))
  1877 in
  1868 in
  1878   map (test_prove @{context}) (rep_goals 3000)
  1869   map (test_prove @{context}) (rep_goals 3000)
  1879 end*}
  1870 end*}
  2038   giving a list of strings that should be used for the replacement of the
  2029   giving a list of strings that should be used for the replacement of the
  2039   variables. For this we implement the function which takes a list of strings
  2030   variables. For this we implement the function which takes a list of strings
  2040   and uses them as name in the outermost abstractions.
  2031   and uses them as name in the outermost abstractions.
  2041 *}
  2032 *}
  2042 
  2033 
  2043 ML{*fun rename_allq [] t = t
  2034 ML %grayML{*fun rename_allq [] t = t
  2044   | rename_allq (x::xs) (Const (@{const_name "All"}, U) $ Abs (_, T, t)) = 
  2035   | rename_allq (x::xs) (Const (@{const_name "All"}, U) $ Abs (_, T, t)) = 
  2045       Const (@{const_name "All"}, U) $ Abs (x, T, rename_allq xs t)
  2036       Const (@{const_name "All"}, U) $ Abs (x, T, rename_allq xs t)
  2046   | rename_allq xs (Const (@{const_name "Trueprop"}, U) $ t) =
  2037   | rename_allq xs (Const (@{const_name "Trueprop"}, U) $ t) =
  2047       rename_allq xs t
  2038       rename_allq xs t
  2048   | rename_allq _ t = t*}
  2039   | rename_allq _ t = t*}
  2115   version of the attribute @{text "[symmetric]"}. The purpose of this attribute is
  2106   version of the attribute @{text "[symmetric]"}. The purpose of this attribute is
  2116   to produce the ``symmetric'' version of an equation. The main function behind 
  2107   to produce the ``symmetric'' version of an equation. The main function behind 
  2117   this attribute is
  2108   this attribute is
  2118 *}
  2109 *}
  2119 
  2110 
  2120 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  2111 ML %grayML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  2121 
  2112 
  2122 text {* 
  2113 text {* 
  2123   where the function @{ML_ind  rule_attribute in Thm} expects a function taking a 
  2114   where the function @{ML_ind  rule_attribute in Thm} expects a function taking a 
  2124   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  2115   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  2125   returns another theorem (namely @{text thm} resolved with the theorem 
  2116   returns another theorem (namely @{text thm} resolved with the theorem 
  2162   An alternative for setting up an attribute is the function @{ML_ind  setup in Attrib}.
  2153   An alternative for setting up an attribute is the function @{ML_ind  setup in Attrib}.
  2163   So instead of using \isacommand{attribute\_setup}, you can also set up the
  2154   So instead of using \isacommand{attribute\_setup}, you can also set up the
  2164   attribute as follows:
  2155   attribute as follows:
  2165 *}
  2156 *}
  2166 
  2157 
  2167 ML{*Attrib.setup @{binding "my_sym"} (Scan.succeed my_symmetric)
  2158 ML %grayML{*Attrib.setup @{binding "my_sym"} (Scan.succeed my_symmetric)
  2168   "applying the sym rule" *}
  2159   "applying the sym rule" *}
  2169 
  2160 
  2170 text {*
  2161 text {*
  2171   This gives a function from @{ML_type "theory -> theory"}, which
  2162   This gives a function from @{ML_type "theory -> theory"}, which
  2172   can be used for example with \isacommand{setup} or with
  2163   can be used for example with \isacommand{setup} or with
  2176   our own version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems
  2167   our own version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems
  2177   as argument and resolve the theorem with this list (one theorem 
  2168   as argument and resolve the theorem with this list (one theorem 
  2178   after another). The code for this attribute is
  2169   after another). The code for this attribute is
  2179 *}
  2170 *}
  2180 
  2171 
  2181 ML{*fun MY_THEN thms = 
  2172 ML %grayML{*fun MY_THEN thms = 
  2182 let
  2173 let
  2183   fun RS_rev thm1 thm2 = thm2 RS thm1
  2174   fun RS_rev thm1 thm2 = thm2 RS thm1
  2184 in
  2175 in
  2185   Thm.rule_attribute (fn _ => fn thm => fold RS_rev thms thm)
  2176   Thm.rule_attribute (fn _ => fn thm => fold RS_rev thms thm)
  2186 end*}
  2177 end*}
  2235   or deletes a theorem from the current simpset. For these applications, you
  2226   or deletes a theorem from the current simpset. For these applications, you
  2236   can use @{ML_ind declaration_attribute in Thm}. To illustrate this function,
  2227   can use @{ML_ind declaration_attribute in Thm}. To illustrate this function,
  2237   let us introduce a theorem list.
  2228   let us introduce a theorem list.
  2238 *}
  2229 *}
  2239 
  2230 
  2240 ML{*structure MyThms = Named_Thms
  2231 ML %grayML{*structure MyThms = Named_Thms
  2241   (val name = @{binding "attr_thms"} 
  2232   (val name = @{binding "attr_thms"} 
  2242    val description = "Theorems for an Attribute") *}
  2233    val description = "Theorems for an Attribute") *}
  2243 
  2234 
  2244 text {* 
  2235 text {* 
  2245   We are going to modify this list by adding and deleting theorems.
  2236   We are going to modify this list by adding and deleting theorems.
  2246   For this we use the two functions @{ML MyThms.add_thm} and
  2237   For this we use the two functions @{ML MyThms.add_thm} and
  2247   @{ML MyThms.del_thm}. You can turn them into attributes 
  2238   @{ML MyThms.del_thm}. You can turn them into attributes 
  2248   with the code
  2239   with the code
  2249 *}
  2240 *}
  2250 
  2241 
  2251 ML{*val my_add = Thm.declaration_attribute MyThms.add_thm
  2242 ML %grayML{*val my_add = Thm.declaration_attribute MyThms.add_thm
  2252 val my_del = Thm.declaration_attribute MyThms.del_thm *}
  2243 val my_del = Thm.declaration_attribute MyThms.del_thm *}
  2253 
  2244 
  2254 text {* 
  2245 text {* 
  2255   and set up the attributes as follows
  2246   and set up the attributes as follows
  2256 *}
  2247 *}
  2340   string}. This can be done with the function @{ML_ind  string_of in Pretty}. In what
  2331   string}. This can be done with the function @{ML_ind  string_of in Pretty}. In what
  2341   follows we will use the following wrapper function for printing a pretty
  2332   follows we will use the following wrapper function for printing a pretty
  2342   type:
  2333   type:
  2343 *}
  2334 *}
  2344 
  2335 
  2345 ML{*fun pprint prt = tracing (Pretty.string_of prt)*}
  2336 ML %grayML{*fun pprint prt = tracing (Pretty.string_of prt)*}
  2346 
  2337 
  2347 text {*
  2338 text {*
  2348   The point of the pretty-printing infrastructure is to give hints about how to
  2339   The point of the pretty-printing infrastructure is to give hints about how to
  2349   layout text and let Isabelle do the actual layout. Let us first explain
  2340   layout text and let Isabelle do the actual layout. Let us first explain
  2350   how you can insert places where a line break can occur. For this assume the
  2341   how you can insert places where a line break can occur. For this assume the
  2351   following function that replicates a string n times:
  2342   following function that replicates a string n times:
  2352 *}
  2343 *}
  2353 
  2344 
  2354 ML{*fun rep n str = implode (replicate n str) *}
  2345 ML %grayML{*fun rep n str = implode (replicate n str) *}
  2355 
  2346 
  2356 text {*
  2347 text {*
  2357   and suppose we want to print out the string:
  2348   and suppose we want to print out the string:
  2358 *}
  2349 *}
  2359 
  2350 
  2360 ML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*}
  2351 ML %grayML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*}
  2361 
  2352 
  2362 text {*
  2353 text {*
  2363   We deliberately chose a large string so that it spans over more than one line. 
  2354   We deliberately chose a large string so that it spans over more than one line. 
  2364   If we print out the string using the usual ``quick-and-dirty'' method, then
  2355   If we print out the string using the usual ``quick-and-dirty'' method, then
  2365   we obtain the ugly output:
  2356   we obtain the ugly output: