ProgTutorial/FirstSteps.thy
changeset 325 352e31d9dacc
parent 324 4172c0743cf2
child 326 f76135c6c527
equal deleted inserted replaced
324:4172c0743cf2 325:352e31d9dacc
   264 text {*
   264 text {*
   265   The easiest way to get the string of a theorem is to transform it
   265   The easiest way to get the string of a theorem is to transform it
   266   into a @{ML_type term} using the function @{ML_ind prop_of}. 
   266   into a @{ML_type term} using the function @{ML_ind prop_of}. 
   267 *}
   267 *}
   268 
   268 
   269 ML {* Thm.rep_thm @{thm mp} *}
       
   270 
       
   271 ML{*fun string_of_thm ctxt thm =
   269 ML{*fun string_of_thm ctxt thm =
   272   Syntax.string_of_term ctxt (prop_of thm)*}
   270   string_of_term ctxt (prop_of thm)*}
   273 
   271 
   274 text {*
   272 text {*
   275   Theorems also include schematic variables, such as @{text "?P"}, 
   273   Theorems also include schematic variables, such as @{text "?P"}, 
   276   @{text "?Q"} and so on. They are needed in order to able to
   274   @{text "?Q"} and so on. They are needed in order to able to
   277   instantiate theorems when they are applied. For example the theorem 
   275   instantiate theorems when they are applied. For example the theorem 
   294 in
   292 in
   295   thm'
   293   thm'
   296 end
   294 end
   297 
   295 
   298 fun string_of_thm_no_vars ctxt thm =
   296 fun string_of_thm_no_vars ctxt thm =
   299   Syntax.string_of_term ctxt (prop_of (no_vars ctxt thm))*}
   297   string_of_term ctxt (prop_of (no_vars ctxt thm))*}
   300 
   298 
   301 text {* 
   299 text {* 
   302   Theorem @{thm [source] conjI} is now printed as follows:
   300   Theorem @{thm [source] conjI} is now printed as follows:
   303 
   301 
   304   @{ML_response_fake [display, gray]
   302   @{ML_response_fake [display, gray]
   636   sometimes necessary to do some ``plumbing'' in order to fit functions
   634   sometimes necessary to do some ``plumbing'' in order to fit functions
   637   together. We have already seen such plumbing in the function @{ML
   635   together. We have already seen such plumbing in the function @{ML
   638   apply_fresh_args}, where @{ML curry} is needed for making the function @{ML
   636   apply_fresh_args}, where @{ML curry} is needed for making the function @{ML
   639   list_comb} that works over pairs to fit with the combinator @{ML "|>"}. Such 
   637   list_comb} that works over pairs to fit with the combinator @{ML "|>"}. Such 
   640   plumbing is also needed in situations where a functions operate over lists, 
   638   plumbing is also needed in situations where a functions operate over lists, 
   641   but one calculates only with a single entity. An example is the function 
   639   but one calculates only with a single element. An example is the function 
   642   @{ML_ind  check_terms in Syntax}, whose purpose is to type-check a list 
   640   @{ML_ind  check_terms in Syntax}, whose purpose is to type-check a list 
   643   of terms.
   641   of terms.
   644 
   642 
   645   @{ML_response_fake [display, gray]
   643   @{ML_response_fake [display, gray]
   646   "let
   644   "let
   653 end"
   651 end"
   654   "m + n, m * n, m - n"}
   652   "m + n, m * n, m - n"}
   655 *}
   653 *}
   656 
   654 
   657 text {*
   655 text {*
   658   In this example we obtain three terms where @{text m} and @{text n} are of
   656   In this example we obtain three terms in which @{text m} and @{text n} are of
   659   type @{typ "nat"}. However, if you have only a single term, then @{ML
   657   type @{typ "nat"}. If you have only a single term, then @{ML
   660   check_terms in Syntax} needs plumbing. This can be done with the function
   658   check_terms in Syntax} needs plumbing. This can be done with the function
   661   @{ML singleton}.\footnote{There is already a function @{ML check_term in
   659   @{ML singleton}.\footnote{There is already a function @{ML check_term in
   662   Syntax} in the Isabelle sources that is defined in terms of @{ML singleton}
   660   Syntax} in the Isabelle sources that is defined in terms of @{ML singleton}
   663   and @{ML check_terms in Syntax}.} For example
   661   and @{ML check_terms in Syntax}.} For example
   664 
   662 
   690 
   688 
   691 text {*
   689 text {*
   692   The main advantage of embedding all code in a theory is that the code can
   690   The main advantage of embedding all code in a theory is that the code can
   693   contain references to entities defined on the logical level of Isabelle. By
   691   contain references to entities defined on the logical level of Isabelle. By
   694   this we mean definitions, theorems, terms and so on. This kind of reference
   692   this we mean definitions, theorems, terms and so on. This kind of reference
   695   is realised with ML-antiquotations, often just called
   693   is realised in Isabelle with ML-antiquotations, often just called
   696   antiquotations.\footnote{There are two kinds of antiquotations in Isabelle,
   694   antiquotations.\footnote{There are two kinds of antiquotations in Isabelle,
   697   which have very different purpose and infrastructures. The first kind,
   695   which have very different purposes and infrastructures. The first kind,
   698   described in this section, are \emph{ML-antiquotations}. They are used to
   696   described in this section, are \emph{ML-antiquotations}. They are used to
   699   refer to entities (like terms, types etc) from Isabelle's logic layer inside
   697   refer to entities (like terms, types etc) from Isabelle's logic layer inside
   700   ML-code. The other kind of antiquotations are \emph{document}
   698   ML-code. The other kind of antiquotations are \emph{document}
   701   antiquotations. They are used only in the text parts of Isabelle and their
   699   antiquotations. They are used only in the text parts of Isabelle and their
   702   purpose is to print logical entities inside \LaTeX-documents. They are part
   700   purpose is to print logical entities inside \LaTeX-documents. Document
   703   of the user level and therefore we are not interested in them in this
   701   antiquotations are part of the user level and therefore we are not
   704   Tutorial, except in Appendix \ref{rec:docantiquotations} where we show how
   702   interested in them in this Tutorial, except in Appendix
   705   to implement your own document antiquotations.}  For example, one can print
   703   \ref{rec:docantiquotations} where we show how to implement your own document
   706   out the name of the current theory by typing
   704   antiquotations.}  For example, one can print out the name of the current
       
   705   theory by typing
       
   706 
   707   
   707   
   708   @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""}
   708   @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""}
   709  
   709  
   710   where @{text "@{theory}"} is an antiquotation that is substituted with the
   710   where @{text "@{theory}"} is an antiquotation that is substituted with the
   711   current theory (remember that we assumed we are inside the theory 
   711   current theory (remember that we assumed we are inside the theory 
   784   @{ML_ind  define in LocalTheory}.  This function is used below to define 
   784   @{ML_ind  define in LocalTheory}.  This function is used below to define 
   785   the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}.
   785   the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}.
   786 *}
   786 *}
   787   
   787   
   788 local_setup %gray {* 
   788 local_setup %gray {* 
   789   snd o LocalTheory.define Thm.internalK 
   789   LocalTheory.define Thm.internalK 
   790     ((@{binding "TrueConj"}, NoSyn), 
   790     ((@{binding "TrueConj"}, NoSyn), 
   791      (Attrib.empty_binding, @{term "True \<and> True"})) *}
   791       (Attrib.empty_binding, @{term "True \<and> True"})) #> snd *}
   792 
   792 
   793 text {* 
   793 text {* 
   794   Now querying the definition you obtain:
   794   Now querying the definition you obtain:
   795 
   795 
   796   \begin{isabelle}
   796   \begin{isabelle}
   811   this restriction, you can implement your own using the function @{ML_ind
   811   this restriction, you can implement your own using the function @{ML_ind
   812   ML_Antiquote.inline}. The code for the antiquotation @{text "term_pat"} is
   812   ML_Antiquote.inline}. The code for the antiquotation @{text "term_pat"} is
   813   as follows.
   813   as follows.
   814 *}
   814 *}
   815 
   815 
   816 ML %linenosgray{*ML_Antiquote.inline "term_pat"
   816 ML %linenosgray{*let
   817   (Args.context -- Scan.lift Args.name_source >>
   817   val parser = Args.context -- Scan.lift Args.name_source
   818      (fn (ctxt, s) =>
   818 
   819        s |> ProofContext.read_term_pattern ctxt
   819   fun term_pat (ctxt, str) =
       
   820      str |> ProofContext.read_term_pattern ctxt
   820          |> ML_Syntax.print_term
   821          |> ML_Syntax.print_term
   821          |> ML_Syntax.atomic))*}
   822          |> ML_Syntax.atomic
       
   823 in
       
   824   ML_Antiquote.inline "term_pat" (parser >> term_pat)
       
   825 end*}
   822 
   826 
   823 text {*
   827 text {*
   824   The parser in Line 2 provides us with a context and a string; this string is
   828   The parser in Line 2 provides us with a context and a string; this string is
   825   transformed into a term using the function @{ML_ind read_term_pattern in
   829   transformed into a term using the function @{ML_ind read_term_pattern in
   826   ProofContext} (Line 4); the next two lines transform the term into a string
   830   ProofContext} (Line 5); the next two lines transform the term into a string
   827   so that the ML-system can understand them. The function @{ML_ind atomic in
   831   so that the ML-system can understand them. An example for the usage
   828   ML_Syntax} just encloses the term in parentheses. An example for the usage
       
   829   of this antiquotation is:
   832   of this antiquotation is:
   830 
   833 
   831   @{ML_response_fake [display,gray]
   834   @{ML_response_fake [display,gray]
   832   "@{term_pat \"Suc (?x::nat)\"}"
   835   "@{term_pat \"Suc (?x::nat)\"}"
   833   "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"}
   836   "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"}
   839   for most antiquotations. Most of the basic operations on ML-syntax are implemented 
   842   for most antiquotations. Most of the basic operations on ML-syntax are implemented 
   840   in @{ML_file "Pure/ML/ml_syntax.ML"}.
   843   in @{ML_file "Pure/ML/ml_syntax.ML"}.
   841   \end{readmore}
   844   \end{readmore}
   842 *}
   845 *}
   843 
   846 
   844 section {* Storing Data (TBD) *}
   847 section {* Storing Data in Isabelle (TBD) *}
   845 
   848 
   846 text {*
   849 text {*
   847   Isabelle provides a mechanism to store (and retrieve) arbitrary data. Before we 
   850   Isabelle provides mechanisms to store (and retrieve) arbitrary data. Before we 
   848   explain this mechanism, let us digress a bit. Convenitional wisdom is that the 
   851   explain them, let us digress: Convenitional wisdom has it that 
   849   type-system of ML ensures that for example an @{ML_type "'a list"} can only
   852   ML's type-system ensures that for example an @{ML_type "'a list"} can only
   850   hold elements of type @{ML_type "'a"}.
   853   hold elements of the same type, namely @{ML_type "'a"}. Still, by some arguably
   851 *}
   854   accidental features of ML, one can implement a universal type. In Isabelle it
   852 
   855   is implemented as @{ML_type Universal.universal}. This type allows one to
   853 ML{*signature UNIVERSAL_TYPE =
   856   inject and project elements of different type into for example into a list.
   854 sig
   857   We will show this by storing an integer and boolean in a list. What is important
   855   type t
   858   that access to the data is done in a type-safe manner. 
   856 
   859 
   857   val embed: unit -> ('a -> t) * (t -> 'a option)
   860   Let us first define projection and injection functions for booleans and integers.
       
   861 *}
       
   862 
       
   863 ML{*local
       
   864   val fn_int  = Universal.tag () : int  Universal.tag
       
   865   val fn_bool = Universal.tag () : bool Universal.tag
       
   866 in
       
   867   val inject_int   = Universal.tagInject fn_int;
       
   868   val inject_bool  = Universal.tagInject fn_bool;
       
   869   val project_int  = Universal.tagProject fn_int;
       
   870   val project_bool = Universal.tagProject fn_bool
   858 end*}
   871 end*}
   859 
   872 
   860 ML{*structure U:> UNIVERSAL_TYPE =
   873 text {*
   861    struct
   874   We can now build a list injecting @{ML_text "13"} and @{ML_text "true"} as
   862       type t = exn
   875   its two elements.
   863 
   876 *}
   864       fun 'a embed () =
   877 
   865          let
   878 ML{* val list = [inject_int 13, inject_bool true]*}
   866             exception E of 'a
   879 
   867             fun project (e: t): 'a option =
   880 ML {*
   868                case e of
   881  project_int (nth list 0)
   869                   E a => SOME a
   882 *}
   870                 | _ => NONE
   883 
   871          in
   884 ML {*
   872             (E, project)
   885  project_bool (nth list 1)
   873          end
   886 *}
   874    end*}
   887 
   875 
   888 (**************************************************)
   876 text {*
   889 (* bak                                            *)
   877   The idea is that type t is the universal type and that each call to embed
   890 (**************************************************)
   878   returns a new pair of functions (inject, project), where inject embeds a
       
   879   value into the universal type and project extracts the value from the
       
   880   universal type. A pair (inject, project) returned by embed works together in
       
   881   that project u will return SOME v if and only if u was created by inject
       
   882   v. If u was created by a different function inject', then project returns
       
   883   NONE.
       
   884 
       
   885   in library.ML
       
   886 *}
       
   887 
       
   888 ML_val{*structure Object = struct type T = exn end; *}
       
   889 
       
   890 ML{*functor Test (U: UNIVERSAL_TYPE): sig end =
       
   891    struct
       
   892       val (intIn: int -> U.t, intOut) = U.embed ()
       
   893       val r: U.t ref = ref (intIn 13)
       
   894       val s1 =
       
   895          case intOut (!r) of
       
   896             NONE => "NONE"
       
   897           | SOME i => Int.toString i
       
   898       val (realIn: real -> U.t, realOut) = U.embed ()
       
   899       val _ = r := realIn 13.0
       
   900       val s2 =
       
   901          case intOut (!r) of
       
   902             NONE => "NONE"
       
   903           | SOME i => Int.toString i
       
   904       val s3 =
       
   905          case realOut (!r) of
       
   906             NONE => "NONE"
       
   907           | SOME x => Real.toString x
       
   908       val _ = tracing (implode [s1, " ", s2, " ", s3, "\n"])
       
   909    end*}
       
   910 
       
   911 ML_val{*structure t = Test(U) *} 
       
   912 
       
   913 ML_val{*structure Datatab = Table(type key = int val ord = int_ord);*}
       
   914 
       
   915 ML {* LocalTheory.restore *}
       
   916 ML {* LocalTheory.set_group *}
       
   917 
       
   918 
       
   919 
   891 
   920 (*
   892 (*
   921 section {* Do Not Try This At Home! *}
   893 section {* Do Not Try This At Home! *}
   922 
   894 
   923 ML {* val my_thms = ref ([]: thm list) *}
   895 ML {* val my_thms = ref ([]: thm list) *}