159 we just use the functions @{ML_ind writeln in Pretty} from the structure |
152 we just use the functions @{ML_ind writeln in Pretty} from the structure |
160 @{ML_struct Pretty} and @{ML_ind pretty_term in Syntax} from the structure |
153 @{ML_struct Pretty} and @{ML_ind pretty_term in Syntax} from the structure |
161 @{ML_struct Syntax}. For more convenience, we bind them to the toplevel. |
154 @{ML_struct Syntax}. For more convenience, we bind them to the toplevel. |
162 *} |
155 *} |
163 |
156 |
164 ML{*val pretty_term = Syntax.pretty_term |
157 ML %grayML{*val pretty_term = Syntax.pretty_term |
165 val pwriteln = Pretty.writeln*} |
158 val pwriteln = Pretty.writeln*} |
166 |
159 |
167 text {* |
160 text {* |
168 They can now be used as follows |
161 They can now be used as follows |
169 |
162 |
174 If there is more than one term to be printed, you can use the |
167 If there is more than one term to be printed, you can use the |
175 function @{ML_ind commas in Pretty} and @{ML_ind block in Pretty} |
168 function @{ML_ind commas in Pretty} and @{ML_ind block in Pretty} |
176 to separate them. |
169 to separate them. |
177 *} |
170 *} |
178 |
171 |
179 ML{*fun pretty_terms ctxt trms = |
172 ML %grayML{*fun pretty_terms ctxt trms = |
180 Pretty.block (Pretty.commas (map (pretty_term ctxt) trms))*} |
173 Pretty.block (Pretty.commas (map (pretty_term ctxt) trms))*} |
181 |
174 |
182 text {* |
175 text {* |
183 You can also print out terms together with their typing information. |
176 You can also print out terms together with their typing information. |
184 For this you need to set the configuration value |
177 For this you need to set the configuration value |
185 @{ML_ind show_types in Syntax} to @{ML true}. |
178 @{ML_ind show_types in Syntax} to @{ML true}. |
186 *} |
179 *} |
187 |
180 |
188 ML{*val show_types_ctxt = Config.put show_types true @{context}*} |
181 ML %grayML{*val show_types_ctxt = Config.put show_types true @{context}*} |
189 |
182 |
190 text {* |
183 text {* |
191 Now by using this context @{ML pretty_term} prints out |
184 Now by using this context @{ML pretty_term} prints out |
192 |
185 |
193 @{ML_response_fake [display, gray] |
186 @{ML_response_fake [display, gray] |
220 \end{itemize} |
213 \end{itemize} |
221 |
214 |
222 A @{ML_type cterm} can be printed with the following function. |
215 A @{ML_type cterm} can be printed with the following function. |
223 *} |
216 *} |
224 |
217 |
225 ML{*fun pretty_cterm ctxt ctrm = |
218 ML %grayML %grayML{*fun pretty_cterm ctxt ctrm = |
226 pretty_term ctxt (term_of ctrm)*} |
219 pretty_term ctxt (term_of ctrm)*} |
227 |
220 |
228 text {* |
221 text {* |
229 Here the function @{ML_ind term_of in Thm} extracts the @{ML_type |
222 Here the function @{ML_ind term_of in Thm} extracts the @{ML_type |
230 term} from a @{ML_type cterm}. More than one @{ML_type cterm}s can be |
223 term} from a @{ML_type cterm}. More than one @{ML_type cterm}s can be |
231 printed again with @{ML commas in Pretty}. |
224 printed again with @{ML commas in Pretty}. |
232 *} |
225 *} |
233 |
226 |
234 ML{*fun pretty_cterms ctxt ctrms = |
227 ML %grayML{*fun pretty_cterms ctxt ctrms = |
235 Pretty.block (Pretty.commas (map (pretty_cterm ctxt) ctrms))*} |
228 Pretty.block (Pretty.commas (map (pretty_cterm ctxt) ctrms))*} |
236 |
229 |
237 text {* |
230 text {* |
238 The easiest way to get the string of a theorem is to transform it |
231 The easiest way to get the string of a theorem is to transform it |
239 into a @{ML_type term} using the function @{ML_ind prop_of in Thm}. |
232 into a @{ML_type term} using the function @{ML_ind prop_of in Thm}. |
240 *} |
233 *} |
241 |
234 |
242 ML{*fun pretty_thm ctxt thm = |
235 ML %grayML{*fun pretty_thm ctxt thm = |
243 pretty_term ctxt (prop_of thm)*} |
236 pretty_term ctxt (prop_of thm)*} |
244 |
237 |
245 text {* |
238 text {* |
246 Theorems include schematic variables, such as @{text "?P"}, |
239 Theorems include schematic variables, such as @{text "?P"}, |
247 @{text "?Q"} and so on. They are needed in Isabelle in order to able to |
240 @{text "?Q"} and so on. They are needed in Isabelle in order to able to |
255 |
248 |
256 However, in order to improve the readability when printing theorems, we |
249 However, in order to improve the readability when printing theorems, we |
257 can switch off the question marks as follows: |
250 can switch off the question marks as follows: |
258 *} |
251 *} |
259 |
252 |
260 ML{*fun pretty_thm_no_vars ctxt thm = |
253 ML %grayML{*fun pretty_thm_no_vars ctxt thm = |
261 let |
254 let |
262 val ctxt' = Config.put show_question_marks false ctxt |
255 val ctxt' = Config.put show_question_marks false ctxt |
263 in |
256 in |
264 pretty_term ctxt' (prop_of thm) |
257 pretty_term ctxt' (prop_of thm) |
265 end*} |
258 end*} |
273 |
266 |
274 Again the functions @{ML commas} and @{ML block in Pretty} help |
267 Again the functions @{ML commas} and @{ML block in Pretty} help |
275 with printing more than one theorem. |
268 with printing more than one theorem. |
276 *} |
269 *} |
277 |
270 |
278 ML{*fun pretty_thms ctxt thms = |
271 ML %grayML{*fun pretty_thms ctxt thms = |
279 Pretty.block (Pretty.commas (map (pretty_thm ctxt) thms)) |
272 Pretty.block (Pretty.commas (map (pretty_thm ctxt) thms)) |
280 |
273 |
281 fun pretty_thms_no_vars ctxt thms = |
274 fun pretty_thms_no_vars ctxt thms = |
282 Pretty.block (Pretty.commas (map (pretty_thm_no_vars ctxt) thms))*} |
275 Pretty.block (Pretty.commas (map (pretty_thm_no_vars ctxt) thms))*} |
283 |
276 |
284 text {* |
277 text {* |
285 Printing functions for @{ML_type typ} are |
278 Printing functions for @{ML_type typ} are |
286 *} |
279 *} |
287 |
280 |
288 ML{*fun pretty_typ ctxt ty = Syntax.pretty_typ ctxt ty |
281 ML %grayML{*fun pretty_typ ctxt ty = Syntax.pretty_typ ctxt ty |
289 fun pretty_typs ctxt tys = |
282 fun pretty_typs ctxt tys = |
290 Pretty.block (Pretty.commas (map (pretty_typ ctxt) tys))*} |
283 Pretty.block (Pretty.commas (map (pretty_typ ctxt) tys))*} |
291 |
284 |
292 text {* |
285 text {* |
293 respectively @{ML_type ctyp} |
286 respectively @{ML_type ctyp} |
294 *} |
287 *} |
295 |
288 |
296 ML{*fun pretty_ctyp ctxt cty = pretty_typ ctxt (typ_of cty) |
289 ML %grayML{*fun pretty_ctyp ctxt cty = pretty_typ ctxt (typ_of cty) |
297 fun pretty_ctyps ctxt ctys = |
290 fun pretty_ctyps ctxt ctys = |
298 Pretty.block (Pretty.commas (map (pretty_ctyp ctxt) ctys))*} |
291 Pretty.block (Pretty.commas (map (pretty_ctyp ctxt) ctys))*} |
299 |
292 |
300 text {* |
293 text {* |
301 \begin{readmore} |
294 \begin{readmore} |
353 |
346 |
354 The simplest combinator is @{ML_ind I in Library}, which is just the |
347 The simplest combinator is @{ML_ind I in Library}, which is just the |
355 identity function defined as |
348 identity function defined as |
356 *} |
349 *} |
357 |
350 |
358 ML{*fun I x = x*} |
351 ML %grayML{*fun I x = x*} |
359 |
352 |
360 text {* |
353 text {* |
361 Another simple combinator is @{ML_ind K in Library}, defined as |
354 Another simple combinator is @{ML_ind K in Library}, defined as |
362 *} |
355 *} |
363 |
356 |
364 ML{*fun K x = fn _ => x*} |
357 ML %grayML{*fun K x = fn _ => x*} |
365 |
358 |
366 text {* |
359 text {* |
367 @{ML K} ``wraps'' a function around @{text "x"} that ignores its argument. As a |
360 @{ML K} ``wraps'' a function around @{text "x"} that ignores its argument. As a |
368 result, @{ML K} defines a constant function always returning @{text x}. |
361 result, @{ML K} defines a constant function always returning @{text x}. |
369 |
362 |
370 The next combinator is reverse application, @{ML_ind "|>" in Basics}, defined as: |
363 The next combinator is reverse application, @{ML_ind "|>" in Basics}, defined as: |
371 *} |
364 *} |
372 |
365 |
373 ML{*fun x |> f = f x*} |
366 ML %grayML{*fun x |> f = f x*} |
374 |
367 |
375 text {* While just syntactic sugar for the usual function application, |
368 text {* While just syntactic sugar for the usual function application, |
376 the purpose of this combinator is to implement functions in a |
369 the purpose of this combinator is to implement functions in a |
377 ``waterfall fashion''. Consider for example the function *} |
370 ``waterfall fashion''. Consider for example the function *} |
378 |
371 |
392 manner. This kind of coding should be familiar, if you have been exposed to |
385 manner. This kind of coding should be familiar, if you have been exposed to |
393 Haskell's {\it do}-notation. Writing the function @{ML inc_by_five} using |
386 Haskell's {\it do}-notation. Writing the function @{ML inc_by_five} using |
394 the reverse application is much clearer than writing |
387 the reverse application is much clearer than writing |
395 *} |
388 *} |
396 |
389 |
397 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*} |
390 ML %grayML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*} |
398 |
391 |
399 text {* or *} |
392 text {* or *} |
400 |
393 |
401 ML{*fun inc_by_five x = |
394 ML %grayML{*fun inc_by_five x = |
402 ((fn x => x + 4) o fst o (fn x => (x, x)) o (fn x => x + 1)) x*} |
395 ((fn x => x + 4) o fst o (fn x => (x, x)) o (fn x => x + 1)) x*} |
403 |
396 |
404 text {* and typographically more economical than *} |
397 text {* and typographically more economical than *} |
405 |
398 |
406 ML{*fun inc_by_five x = |
399 ML %grayML{*fun inc_by_five x = |
407 let val y1 = x + 1 |
400 let val y1 = x + 1 |
408 val y2 = (y1, y1) |
401 val y2 = (y1, y1) |
409 val y3 = fst y2 |
402 val y3 = fst y2 |
410 val y4 = y3 + 4 |
403 val y4 = y3 + 4 |
411 in y4 end*} |
404 in y4 end*} |
533 The combinator @{ML_ind "`" in Basics} (a backtick) is similar to @{ML tap}, |
526 The combinator @{ML_ind "`" in Basics} (a backtick) is similar to @{ML tap}, |
534 but applies a function to the value and returns the result together with the |
527 but applies a function to the value and returns the result together with the |
535 value (as a pair). It is defined as |
528 value (as a pair). It is defined as |
536 *} |
529 *} |
537 |
530 |
538 ML{*fun `f = fn x => (f x, x)*} |
531 ML %grayML{*fun `f = fn x => (f x, x)*} |
539 |
532 |
540 text {* |
533 text {* |
541 An example for this combinator is the function |
534 An example for this combinator is the function |
542 *} |
535 *} |
543 |
536 |
544 ML{*fun inc_as_pair x = |
537 ML %grayML{*fun inc_as_pair x = |
545 x |> `(fn x => x + 1) |
538 x |> `(fn x => x + 1) |
546 |> (fn (x, y) => (x, y + 1))*} |
539 |> (fn (x, y) => (x, y + 1))*} |
547 |
540 |
548 text {* |
541 text {* |
549 which takes @{text x} as argument, and then increments @{text x}, but also keeps |
542 which takes @{text x} as argument, and then increments @{text x}, but also keeps |
554 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
547 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
555 defined for functions manipulating pairs. The first applies the function to |
548 defined for functions manipulating pairs. The first applies the function to |
556 the first component of the pair, defined as |
549 the first component of the pair, defined as |
557 *} |
550 *} |
558 |
551 |
559 ML{*fun (x, y) |>> f = (f x, y)*} |
552 ML %grayML{*fun (x, y) |>> f = (f x, y)*} |
560 |
553 |
561 text {* |
554 text {* |
562 and the second combinator to the second component, defined as |
555 and the second combinator to the second component, defined as |
563 *} |
556 *} |
564 |
557 |
565 ML{*fun (x, y) ||> f = (x, f y)*} |
558 ML %grayML{*fun (x, y) ||> f = (x, f y)*} |
566 |
559 |
567 text {* |
560 text {* |
568 These two functions can, for example, be used to avoid explicit @{text "lets"} for |
561 These two functions can, for example, be used to avoid explicit @{text "lets"} for |
569 intermediate values in functions that return pairs. As an example, suppose you |
562 intermediate values in functions that return pairs. As an example, suppose you |
570 want to separate a list of integers into two lists according to a |
563 want to separate a list of integers into two lists according to a |
571 threshold. If the threshold is @{ML "5"}, the list @{ML "[1,6,2,5,3,4]"} |
564 threshold. If the threshold is @{ML "5"}, the list @{ML "[1,6,2,5,3,4]"} |
572 should be separated as @{ML "([1,2,3,4], [6,5])"}. Such a function can be |
565 should be separated as @{ML "([1,2,3,4], [6,5])"}. Such a function can be |
573 implemented as |
566 implemented as |
574 *} |
567 *} |
575 |
568 |
576 ML{*fun separate i [] = ([], []) |
569 ML %grayML{*fun separate i [] = ([], []) |
577 | separate i (x::xs) = |
570 | separate i (x::xs) = |
578 let |
571 let |
579 val (los, grs) = separate i xs |
572 val (los, grs) = separate i xs |
580 in |
573 in |
581 if i <= x then (los, x::grs) else (x::los, grs) |
574 if i <= x then (los, x::grs) else (x::los, grs) |
585 where the return value of the recursive call is bound explicitly to |
578 where the return value of the recursive call is bound explicitly to |
586 the pair @{ML "(los, grs)" for los grs}. However, this function |
579 the pair @{ML "(los, grs)" for los grs}. However, this function |
587 can be implemented more concisely as |
580 can be implemented more concisely as |
588 *} |
581 *} |
589 |
582 |
590 ML{*fun separate i [] = ([], []) |
583 ML %grayML{*fun separate i [] = ([], []) |
591 | separate i (x::xs) = |
584 | separate i (x::xs) = |
592 if i <= x |
585 if i <= x |
593 then separate i xs ||> cons x |
586 then separate i xs ||> cons x |
594 else separate i xs |>> cons x*} |
587 else separate i xs |>> cons x*} |
595 |
588 |
600 |
593 |
601 With the combinator @{ML_ind "|->" in Basics} you can re-combine the |
594 With the combinator @{ML_ind "|->" in Basics} you can re-combine the |
602 elements from a pair. This combinator is defined as |
595 elements from a pair. This combinator is defined as |
603 *} |
596 *} |
604 |
597 |
605 ML{*fun (x, y) |-> f = f x y*} |
598 ML %grayML{*fun (x, y) |-> f = f x y*} |
606 |
599 |
607 text {* |
600 text {* |
608 and can be used to write the following roundabout version |
601 and can be used to write the following roundabout version |
609 of the @{text double} function: |
602 of the @{text double} function: |
610 *} |
603 *} |
611 |
604 |
612 ML{*fun double x = |
605 ML %grayML{*fun double x = |
613 x |> (fn x => (x, x)) |
606 x |> (fn x => (x, x)) |
614 |-> (fn x => fn y => x + y)*} |
607 |-> (fn x => fn y => x + y)*} |
615 |
608 |
616 text {* |
609 text {* |
617 The combinator @{ML_ind ||>> in Basics} plays a central rôle whenever your |
610 The combinator @{ML_ind ||>> in Basics} plays a central rôle whenever your |
668 obtained by previous calls. |
661 obtained by previous calls. |
669 |
662 |
670 A more realistic example for this combinator is the following code |
663 A more realistic example for this combinator is the following code |
671 *} |
664 *} |
672 |
665 |
673 ML{*val (((one_def, two_def), three_def), ctxt') = |
666 ML %grayML{*val (((one_def, two_def), three_def), ctxt') = |
674 @{context} |
667 @{context} |
675 |> Local_Defs.add_def ((@{binding "One"}, NoSyn), @{term "1::nat"}) |
668 |> Local_Defs.add_def ((@{binding "One"}, NoSyn), @{term "1::nat"}) |
676 ||>> Local_Defs.add_def ((@{binding "Two"}, NoSyn), @{term "2::nat"}) |
669 ||>> Local_Defs.add_def ((@{binding "Two"}, NoSyn), @{term "2::nat"}) |
677 ||>> Local_Defs.add_def ((@{binding "Three"}, NoSyn), @{term "3::nat"})*} |
670 ||>> Local_Defs.add_def ((@{binding "Three"}, NoSyn), @{term "3::nat"})*} |
678 |
671 |
701 @{ML_ind "#->" in Basics}, @{ML_ind "#>>" in Basics}, @{ML_ind "##>" in |
694 @{ML_ind "#->" in Basics}, @{ML_ind "#>>" in Basics}, @{ML_ind "##>" in |
702 Basics} and @{ML_ind "##>>" in Basics}. Using @{ML "#->"}, for example, the |
695 Basics} and @{ML_ind "##>>" in Basics}. Using @{ML "#->"}, for example, the |
703 function @{text double} can also be written as: |
696 function @{text double} can also be written as: |
704 *} |
697 *} |
705 |
698 |
706 ML{*val double = |
699 ML %grayML{*val double = |
707 (fn x => (x, x)) #-> |
700 (fn x => (x, x)) #-> |
708 (fn x => fn y => x + y)*} |
701 (fn x => fn y => x + y)*} |
709 |
702 |
710 |
703 |
711 text {* |
704 text {* |
799 |
792 |
800 Note, however, that antiquotations are statically linked, that is their value is |
793 Note, however, that antiquotations are statically linked, that is their value is |
801 determined at ``compile-time'', not at ``run-time''. For example the function |
794 determined at ``compile-time'', not at ``run-time''. For example the function |
802 *} |
795 *} |
803 |
796 |
804 ML{*fun not_current_thyname () = Context.theory_name @{theory} *} |
797 ML %grayML{*fun not_current_thyname () = Context.theory_name @{theory} *} |
805 |
798 |
806 text {* |
799 text {* |
807 does \emph{not} return the name of the current theory, if it is run in a |
800 does \emph{not} return the name of the current theory, if it is run in a |
808 different theory. Instead, the code above defines the constant function |
801 different theory. Instead, the code above defines the constant function |
809 that always returns the string @{text [quotes] "First_Steps"}, no matter where the |
802 that always returns the string @{text [quotes] "First_Steps"}, no matter where the |
854 It is also possible to prove lemmas with the antiquotation @{text "@{lemma \<dots> by \<dots>}"} |
847 It is also possible to prove lemmas with the antiquotation @{text "@{lemma \<dots> by \<dots>}"} |
855 whose first argument is a statement (possibly many of them separated by @{text "and"}) |
848 whose first argument is a statement (possibly many of them separated by @{text "and"}) |
856 and the second is a proof. For example |
849 and the second is a proof. For example |
857 *} |
850 *} |
858 |
851 |
859 ML{*val foo_thm = @{lemma "True" and "False \<Longrightarrow> P" by simp_all} *} |
852 ML %grayML{*val foo_thm = @{lemma "True" and "False \<Longrightarrow> P" by simp_all} *} |
860 |
853 |
861 text {* |
854 text {* |
862 The result can be printed out as follows. |
855 The result can be printed out as follows. |
863 |
856 |
864 @{ML_response_fake [gray,display] |
857 @{ML_response_fake [gray,display] |
934 |
927 |
935 which shows the internal representation of the term @{text "Suc ?x"}. Similarly |
928 which shows the internal representation of the term @{text "Suc ?x"}. Similarly |
936 we can write an antiquotation for type patterns. Its code is |
929 we can write an antiquotation for type patterns. Its code is |
937 *} |
930 *} |
938 |
931 |
939 ML{*val type_pat_setup = |
932 ML %grayML{*val type_pat_setup = |
940 let |
933 let |
941 val parser = Args.context -- Scan.lift Args.name_source |
934 val parser = Args.context -- Scan.lift Args.name_source |
942 |
935 |
943 fun typ_pat (ctxt, str) = |
936 fun typ_pat (ctxt, str) = |
944 let |
937 let |
997 We will show the usage of the universal type by storing an integer and |
990 We will show the usage of the universal type by storing an integer and |
998 a boolean into a single list. Let us first define injection and projection |
991 a boolean into a single list. Let us first define injection and projection |
999 functions for booleans and integers into and from the type @{ML_type Universal.universal}. |
992 functions for booleans and integers into and from the type @{ML_type Universal.universal}. |
1000 *} |
993 *} |
1001 |
994 |
1002 ML{*local |
995 ML %grayML{*local |
1003 val fn_int = Universal.tag () : int Universal.tag |
996 val fn_int = Universal.tag () : int Universal.tag |
1004 val fn_bool = Universal.tag () : bool Universal.tag |
997 val fn_bool = Universal.tag () : bool Universal.tag |
1005 in |
998 in |
1006 val inject_int = Universal.tagInject fn_int; |
999 val inject_int = Universal.tagInject fn_int; |
1007 val inject_bool = Universal.tagInject fn_bool; |
1000 val inject_bool = Universal.tagInject fn_bool; |
1013 Using the injection functions, we can inject the integer @{ML_text "13"} |
1006 Using the injection functions, we can inject the integer @{ML_text "13"} |
1014 and the boolean value @{ML_text "true"} into @{ML_type Universal.universal}, and |
1007 and the boolean value @{ML_text "true"} into @{ML_type Universal.universal}, and |
1015 then store them in a @{ML_type "Universal.universal list"} as follows: |
1008 then store them in a @{ML_type "Universal.universal list"} as follows: |
1016 *} |
1009 *} |
1017 |
1010 |
1018 ML{*val foo_list = |
1011 ML %grayML{*val foo_list = |
1019 let |
1012 let |
1020 val thirteen = inject_int 13 |
1013 val thirteen = inject_int 13 |
1021 val truth_val = inject_bool true |
1014 val truth_val = inject_bool true |
1022 in |
1015 in |
1023 [thirteen, truth_val] |
1016 [thirteen, truth_val] |
1087 it (@{ML Data.map}). There is also the functions @{ML Data.put}, which however is |
1080 it (@{ML Data.map}). There is also the functions @{ML Data.put}, which however is |
1088 not relevant here. Below we define two |
1081 not relevant here. Below we define two |
1089 auxiliary functions, which help us with accessing the table. |
1082 auxiliary functions, which help us with accessing the table. |
1090 *} |
1083 *} |
1091 |
1084 |
1092 ML{*val lookup = Symtab.lookup o Data.get |
1085 ML %grayML{*val lookup = Symtab.lookup o Data.get |
1093 fun update k v = Data.map (Symtab.update (k, v))*} |
1086 fun update k v = Data.map (Symtab.update (k, v))*} |
1094 |
1087 |
1095 text {* |
1088 text {* |
1096 Since we want to store introduction rules associated with their |
1089 Since we want to store introduction rules associated with their |
1097 logical connective, we can fill the table as follows. |
1090 logical connective, we can fill the table as follows. |
1132 defeat its undo-mechanism. To see the latter, consider the |
1125 defeat its undo-mechanism. To see the latter, consider the |
1133 following data container where we maintain a reference to a list of |
1126 following data container where we maintain a reference to a list of |
1134 integers. |
1127 integers. |
1135 *} |
1128 *} |
1136 |
1129 |
1137 ML{*structure WrongRefData = Theory_Data |
1130 ML %grayML{*structure WrongRefData = Theory_Data |
1138 (type T = (int list) Unsynchronized.ref |
1131 (type T = (int list) Unsynchronized.ref |
1139 val empty = Unsynchronized.ref [] |
1132 val empty = Unsynchronized.ref [] |
1140 val extend = I |
1133 val extend = I |
1141 val merge = fst)*} |
1134 val merge = fst)*} |
1142 |
1135 |
1149 "ref []"} |
1142 "ref []"} |
1150 |
1143 |
1151 For updating the reference we use the following function |
1144 For updating the reference we use the following function |
1152 *} |
1145 *} |
1153 |
1146 |
1154 ML{*fun ref_update n = WrongRefData.map |
1147 ML %grayML{*fun ref_update n = WrongRefData.map |
1155 (fn r => let val _ = r := n::(!r) in r end)*} |
1148 (fn r => let val _ = r := n::(!r) in r end)*} |
1156 |
1149 |
1157 text {* |
1150 text {* |
1158 which takes an integer and adds it to the content of the reference. |
1151 which takes an integer and adds it to the content of the reference. |
1159 As before, we update the reference with the command |
1152 As before, we update the reference with the command |
1200 Storing data in a proof context is done in a similar fashion. As mentioned |
1193 Storing data in a proof context is done in a similar fashion. As mentioned |
1201 before, the corresponding functor is @{ML_funct_ind Proof_Data}. With the |
1194 before, the corresponding functor is @{ML_funct_ind Proof_Data}. With the |
1202 following code we can store a list of terms in a proof context. |
1195 following code we can store a list of terms in a proof context. |
1203 *} |
1196 *} |
1204 |
1197 |
1205 ML{*structure Data = Proof_Data |
1198 ML %grayML{*structure Data = Proof_Data |
1206 (type T = term list |
1199 (type T = term list |
1207 fun init _ = [])*} |
1200 fun init _ = [])*} |
1208 |
1201 |
1209 text {* |
1202 text {* |
1210 The init-function we have to specify must produce a list for when a context |
1203 The init-function we have to specify must produce a list for when a context |
1212 context is derived). We choose here to just return the empty list. Next |
1205 context is derived). We choose here to just return the empty list. Next |
1213 we define two auxiliary functions for updating the list with a given |
1206 we define two auxiliary functions for updating the list with a given |
1214 term and printing the list. |
1207 term and printing the list. |
1215 *} |
1208 *} |
1216 |
1209 |
1217 ML{*fun update trm = Data.map (fn trms => trm::trms) |
1210 ML %grayML{*fun update trm = Data.map (fn trms => trm::trms) |
1218 |
1211 |
1219 fun print ctxt = |
1212 fun print ctxt = |
1220 case (Data.get ctxt) of |
1213 case (Data.get ctxt) of |
1221 [] => pwriteln (Pretty.str "Empty!") |
1214 [] => pwriteln (Pretty.str "Empty!") |
1222 | trms => pwriteln (pretty_terms ctxt trms)*} |
1215 | trms => pwriteln (pretty_terms ctxt trms)*} |
1270 above. The first instance implements named theorem lists using the functor |
1263 above. The first instance implements named theorem lists using the functor |
1271 @{ML_funct_ind Named_Thms}. This is because storing theorems in a list |
1264 @{ML_funct_ind Named_Thms}. This is because storing theorems in a list |
1272 is such a common task. To obtain a named theorem list, you just declare |
1265 is such a common task. To obtain a named theorem list, you just declare |
1273 *} |
1266 *} |
1274 |
1267 |
1275 ML{*structure FooRules = Named_Thms |
1268 ML %grayML{*structure FooRules = Named_Thms |
1276 (val name = @{binding "foo"} |
1269 (val name = @{binding "foo"} |
1277 val description = "Theorems for foo") *} |
1270 val description = "Theorems for foo") *} |
1278 |
1271 |
1279 text {* |
1272 text {* |
1280 and set up the @{ML_struct FooRules} with the command |
1273 and set up the @{ML_struct FooRules} with the command |
1337 user to control three values, say @{text bval} containing a boolean, @{text |
1330 user to control three values, say @{text bval} containing a boolean, @{text |
1338 ival} containing an integer and @{text sval} containing a string. These |
1331 ival} containing an integer and @{text sval} containing a string. These |
1339 values can be declared by |
1332 values can be declared by |
1340 *} |
1333 *} |
1341 |
1334 |
1342 ML{*val bval = Attrib.setup_config_bool @{binding "bval"} (K false) |
1335 ML %grayML{*val bval = Attrib.setup_config_bool @{binding "bval"} (K false) |
1343 val ival = Attrib.setup_config_int @{binding "ival"} (K 0) |
1336 val ival = Attrib.setup_config_int @{binding "ival"} (K 0) |
1344 val sval = Attrib.setup_config_string @{binding "sval"} (K "some string") *} |
1337 val sval = Attrib.setup_config_string @{binding "sval"} (K "some string") *} |
1345 |
1338 |
1346 text {* |
1339 text {* |
1347 where each value needs to be given a default. |
1340 where each value needs to be given a default. |