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} |