350 For beginners perhaps the most puzzling parts in the existing code of Isabelle are |
350 For beginners perhaps the most puzzling parts in the existing code of Isabelle are |
351 the combinators. At first they seem to greatly obstruct the |
351 the combinators. At first they seem to greatly obstruct the |
352 comprehension of the code, but after getting familiar with them, they |
352 comprehension of the code, but after getting familiar with them, they |
353 actually ease the understanding and also the programming. |
353 actually ease the understanding and also the programming. |
354 |
354 |
355 The simplest combinator is @{ML_ind I}, which is just the identity function defined as |
355 The simplest combinator is @{ML_ind I in Basic_Library}, which is just the |
|
356 identity function defined as |
356 *} |
357 *} |
357 |
358 |
358 ML{*fun I x = x*} |
359 ML{*fun I x = x*} |
359 |
360 |
360 text {* Another simple combinator is @{ML_ind K}, defined as *} |
361 text {* |
|
362 Another simple combinator is @{ML_ind K in Library}, defined as |
|
363 *} |
361 |
364 |
362 ML{*fun K x = fn _ => x*} |
365 ML{*fun K x = fn _ => x*} |
363 |
366 |
364 text {* |
367 text {* |
365 @{ML_ind K} ``wraps'' a function around the argument @{text "x"}. However, this |
368 @{ML K} ``wraps'' a function around the argument @{text "x"}. However, this |
366 function ignores its argument. As a result, @{ML K} defines a constant function |
369 function ignores its argument. As a result, @{ML K} defines a constant function |
367 always returning @{text x}. |
370 always returning @{text x}. |
368 |
371 |
369 The next combinator is reverse application, @{ML_ind "|>"}, defined as: |
372 The next combinator is reverse application, @{ML_ind "|>" in Basics}, defined as: |
370 *} |
373 *} |
371 |
374 |
372 ML{*fun x |> f = f x*} |
375 ML{*fun x |> f = f x*} |
373 |
376 |
374 text {* While just syntactic sugar for the usual function application, |
377 text {* While just syntactic sugar for the usual function application, |
441 |> string_of_term ctxt |
444 |> string_of_term ctxt |
442 |> tracing |
445 |> tracing |
443 end" |
446 end" |
444 "P z za zb"} |
447 "P z za zb"} |
445 |
448 |
446 You can read off this behaviour from how @{ML apply_fresh_args} is |
449 You can read off this behaviour from how @{ML apply_fresh_args} is coded: in |
447 coded: in Line 2, the function @{ML_ind fastype_of} calculates the type of the |
450 Line 2, the function @{ML_ind fastype_of in Term} calculates the type of the |
448 term; @{ML_ind binder_types} in the next line produces the list of argument |
451 term; @{ML_ind binder_types in Term} in the next line produces the list of |
449 types (in the case above the list @{text "[nat, int, unit]"}); Line 4 |
452 argument types (in the case above the list @{text "[nat, int, unit]"}); Line |
450 pairs up each type with the string @{text "z"}; the |
453 4 pairs up each type with the string @{text "z"}; the function @{ML_ind |
451 function @{ML_ind variant_frees in Variable} generates for each @{text "z"} a |
454 variant_frees in Variable} generates for each @{text "z"} a unique name |
452 unique name avoiding the given @{text f}; the list of name-type pairs is turned |
455 avoiding the given @{text f}; the list of name-type pairs is turned into a |
453 into a list of variable terms in Line 6, which in the last line is applied |
456 list of variable terms in Line 6, which in the last line is applied by the |
454 by the function @{ML_ind list_comb} to the term. In this last step we have to |
457 function @{ML_ind list_comb in Term} to the term. In this last step we have |
455 use the function @{ML_ind curry}, because @{ML_ind list_comb} expects the |
458 to use the function @{ML_ind curry in Library}, because @{ML list_comb} |
456 function and the variables list as a pair. This kind of functions is often needed when |
459 expects the function and the variables list as a pair. This kind of |
457 constructing terms with fresh variables. The infrastructure helps tremendously |
460 functions is often needed when constructing terms with fresh variables. The |
458 to avoid any name clashes. Consider for example: |
461 infrastructure helps tremendously to avoid any name clashes. Consider for |
|
462 example: |
459 |
463 |
460 @{ML_response_fake [display,gray] |
464 @{ML_response_fake [display,gray] |
461 "let |
465 "let |
462 val t = @{term \"za::'a \<Rightarrow> 'b \<Rightarrow> 'c\"} |
466 val t = @{term \"za::'a \<Rightarrow> 'b \<Rightarrow> 'c\"} |
463 val ctxt = @{context} |
467 val ctxt = @{context} |
483 which is the function composed of first the increment-by-one function and then |
487 which is the function composed of first the increment-by-one function and then |
484 increment-by-two, followed by increment-by-three. Again, the reverse function |
488 increment-by-two, followed by increment-by-three. Again, the reverse function |
485 composition allows you to read the code top-down. |
489 composition allows you to read the code top-down. |
486 |
490 |
487 The remaining combinators described in this section add convenience for the |
491 The remaining combinators described in this section add convenience for the |
488 ``waterfall method'' of writing functions. The combinator @{ML_ind tap} allows |
492 ``waterfall method'' of writing functions. The combinator @{ML_ind tap in |
489 you to get hold of an intermediate result (to do some side-calculations for |
493 Basics} allows you to get hold of an intermediate result (to do some |
490 instance). The function |
494 side-calculations for instance). The function |
491 |
|
492 *} |
495 *} |
493 |
496 |
494 ML %linenosgray{*fun inc_by_three x = |
497 ML %linenosgray{*fun inc_by_three x = |
495 x |> (fn x => x + 1) |
498 x |> (fn x => x + 1) |
496 |> tap (fn x => tracing (PolyML.makestring x)) |
499 |> tap (fn x => tracing (PolyML.makestring x)) |
497 |> (fn x => x + 2)*} |
500 |> (fn x => x + 2)*} |
498 |
501 |
499 text {* |
502 text {* |
500 increments the argument first by @{text "1"} and then by @{text "2"}. In the |
503 increments the argument first by @{text "1"} and then by @{text "2"}. In the |
501 middle (Line 3), however, it uses @{ML_ind tap} for printing the ``plus-one'' |
504 middle (Line 3), however, it uses @{ML tap} for printing the ``plus-one'' |
502 intermediate result inside the tracing buffer. The function @{ML_ind tap} can |
505 intermediate result inside the tracing buffer. The function @{ML tap} can |
503 only be used for side-calculations, because any value that is computed |
506 only be used for side-calculations, because any value that is computed |
504 cannot be merged back into the ``main waterfall''. To do this, you can use |
507 cannot be merged back into the ``main waterfall''. To do this, you can use |
505 the next combinator. |
508 the next combinator. |
506 |
509 |
507 The combinator @{ML_ind "`"} (a backtick) is similar to @{ML tap}, but applies a |
510 The combinator @{ML_ind "`" in Basics} (a backtick) is similar to @{ML tap}, |
508 function to the value and returns the result together with the value (as a |
511 but applies a function to the value and returns the result together with the |
509 pair). For example the function |
512 value (as a pair). For example the function |
510 *} |
513 *} |
511 |
514 |
512 ML{*fun inc_as_pair x = |
515 ML{*fun inc_as_pair x = |
513 x |> `(fn x => x + 1) |
516 x |> `(fn x => x + 1) |
514 |> (fn (x, y) => (x, y + 1))*} |
517 |> (fn (x, y) => (x, y + 1))*} |
517 takes @{text x} as argument, and then increments @{text x}, but also keeps |
520 takes @{text x} as argument, and then increments @{text x}, but also keeps |
518 @{text x}. The intermediate result is therefore the pair @{ML "(x + 1, x)" |
521 @{text x}. The intermediate result is therefore the pair @{ML "(x + 1, x)" |
519 for x}. After that, the function increments the right-hand component of the |
522 for x}. After that, the function increments the right-hand component of the |
520 pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}. |
523 pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}. |
521 |
524 |
522 The combinators @{ML_ind "|>>"} and @{ML_ind "||>"} are defined for |
525 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
523 functions manipulating pairs. The first applies the function to |
526 defined for functions manipulating pairs. The first applies the function to |
524 the first component of the pair, defined as |
527 the first component of the pair, defined as |
525 *} |
528 *} |
526 |
529 |
527 ML{*fun (x, y) |>> f = (f x, y)*} |
530 ML{*fun (x, y) |>> f = (f x, y)*} |
528 |
531 |
564 text {* |
567 text {* |
565 avoiding the explicit @{text "let"}. While in this example the gain in |
568 avoiding the explicit @{text "let"}. While in this example the gain in |
566 conciseness is only small, in more complicated situations the benefit of |
569 conciseness is only small, in more complicated situations the benefit of |
567 avoiding @{text "lets"} can be substantial. |
570 avoiding @{text "lets"} can be substantial. |
568 |
571 |
569 With the combinator @{ML_ind "|->"} you can re-combine the elements from a pair. |
572 With the combinator @{ML_ind "|->" in Basics} you can re-combine the |
570 This combinator is defined as |
573 elements from a pair. This combinator is defined as |
571 *} |
574 *} |
572 |
575 |
573 ML{*fun (x, y) |-> f = f x y*} |
576 ML{*fun (x, y) |-> f = f x y*} |
574 |
577 |
575 text {* |
578 text {* |
580 ML{*fun double x = |
583 ML{*fun double x = |
581 x |> (fn x => (x, x)) |
584 x |> (fn x => (x, x)) |
582 |-> (fn x => fn y => x + y)*} |
585 |-> (fn x => fn y => x + y)*} |
583 |
586 |
584 text {* |
587 text {* |
585 The combinator @{ML_ind ||>>} plays a central rôle whenever your task is to update a |
588 The combinator @{ML_ind ||>> in Basics} plays a central rôle whenever your |
586 theory and the update also produces a side-result (for example a theorem). Functions |
589 task is to update a theory and the update also produces a side-result (for |
587 for such tasks return a pair whose second component is the theory and the fist |
590 example a theorem). Functions for such tasks return a pair whose second |
588 component is the side-result. Using @{ML_ind ||>>}, you can do conveniently the update |
591 component is the theory and the fist component is the side-result. Using |
589 and also accumulate the side-results. Consider the following simple function. |
592 @{ML ||>>}, you can do conveniently the update and also |
|
593 accumulate the side-results. Consider the following simple function. |
590 *} |
594 *} |
591 |
595 |
592 ML %linenosgray{*fun acc_incs x = |
596 ML %linenosgray{*fun acc_incs x = |
593 x |> (fn x => ("", x)) |
597 x |> (fn x => ("", x)) |
594 ||>> (fn x => (x, x + 1)) |
598 ||>> (fn x => (x, x + 1)) |
595 ||>> (fn x => (x, x + 1)) |
599 ||>> (fn x => (x, x + 1)) |
596 ||>> (fn x => (x, x + 1))*} |
600 ||>> (fn x => (x, x + 1))*} |
597 |
601 |
598 text {* |
602 text {* |
599 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
603 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
600 @{ML_ind "||>>"} operates on pairs). Each of the next three lines just increment |
604 @{ML ||>>} operates on pairs). Each of the next three lines just increment |
601 the value by one, but also nest the intermediate results to the left. For example |
605 the value by one, but also nest the intermediate results to the left. For example |
602 |
606 |
603 @{ML_response [display,gray] |
607 @{ML_response [display,gray] |
604 "acc_incs 1" |
608 "acc_incs 1" |
605 "((((\"\", 1), 2), 3), 4)"} |
609 "((((\"\", 1), 2), 3), 4)"} |
612 |
616 |
613 \footnote{\bf FIXME: maybe give a ``real world'' example for this combinator.} |
617 \footnote{\bf FIXME: maybe give a ``real world'' example for this combinator.} |
614 *} |
618 *} |
615 |
619 |
616 text {* |
620 text {* |
617 Recall that @{ML_ind "|>"} is the reverse function application. Recall also that |
621 Recall that @{ML "|>"} is the reverse function application. Recall also that |
618 the related |
622 the related reverse function composition is @{ML "#>"}. In fact all the |
619 reverse function composition is @{ML_ind "#>"}. In fact all the combinators |
623 combinators @{ML "|->"}, @{ML "|>>"} , @{ML "||>"} and @{ML "||>>"} |
620 @{ML_ind "|->"}, @{ML_ind "|>>"} , @{ML_ind "||>"} and @{ML_ind |
624 described above have related combinators for function composition, namely |
621 "||>>"} described above have related combinators for |
625 @{ML_ind "#->" in Basics}, @{ML_ind "#>>" in Basics}, @{ML_ind "##>" in |
622 function composition, namely @{ML_ind "#->"}, @{ML_ind "#>>"}, |
626 Basics} and @{ML_ind "##>>" in Basics}. Using @{ML "#->"}, for example, the |
623 @{ML_ind "##>"} and @{ML_ind "##>>"}. |
627 function @{text double} can also be written as: |
624 Using @{ML_ind "#->"}, for example, the function @{text double} can also be written as: |
|
625 *} |
628 *} |
626 |
629 |
627 ML{*val double = |
630 ML{*val double = |
628 (fn x => (x, x)) |
631 (fn x => (x, x)) |
629 #-> (fn x => fn y => x + y)*} |
632 #-> (fn x => fn y => x + y)*} |
635 together. We have already seen such plumbing in the function @{ML |
638 together. We have already seen such plumbing in the function @{ML |
636 apply_fresh_args}, where @{ML curry} is needed for making the function @{ML |
639 apply_fresh_args}, where @{ML curry} is needed for making the function @{ML |
637 list_comb} that works over pairs to fit with the combinator @{ML "|>"}. Such |
640 list_comb} that works over pairs to fit with the combinator @{ML "|>"}. Such |
638 plumbing is also needed in situations where a function operate over lists, |
641 plumbing is also needed in situations where a function operate over lists, |
639 but one calculates only with a single element. An example is the function |
642 but one calculates only with a single element. An example is the function |
640 @{ML_ind check_terms in Syntax}, whose purpose is to type-check a list |
643 @{ML_ind check_terms in Syntax}, whose purpose is to type-check a list |
641 of terms. Consider the code: |
644 of terms. Consider the code: |
642 |
645 |
643 @{ML_response_fake [display, gray] |
646 @{ML_response_fake [display, gray] |
644 "let |
647 "let |
645 val ctxt = @{context} |
648 val ctxt = @{context} |
706 @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""} |
709 @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""} |
707 |
710 |
708 where @{text "@{theory}"} is an antiquotation that is substituted with the |
711 where @{text "@{theory}"} is an antiquotation that is substituted with the |
709 current theory (remember that we assumed we are inside the theory |
712 current theory (remember that we assumed we are inside the theory |
710 @{text FirstSteps}). The name of this theory can be extracted using |
713 @{text FirstSteps}). The name of this theory can be extracted using |
711 the function @{ML_ind theory_name in Context}. |
714 the function @{ML_ind theory_name in Context}. |
712 |
715 |
713 Note, however, that antiquotations are statically linked, that is their value is |
716 Note, however, that antiquotations are statically linked, that is their value is |
714 determined at ``compile-time'', not at ``run-time''. For example the function |
717 determined at ``compile-time'', not at ``run-time''. For example the function |
715 *} |
718 *} |
716 |
719 |
777 @{ML_response [display,gray] |
780 @{ML_response [display,gray] |
778 "@{binding \"name\"}" |
781 "@{binding \"name\"}" |
779 "name"} |
782 "name"} |
780 |
783 |
781 An example where a qualified name is needed is the function |
784 An example where a qualified name is needed is the function |
782 @{ML_ind define in LocalTheory}. This function is used below to define |
785 @{ML_ind define in LocalTheory}. This function is used below to define |
783 the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}. |
786 the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}. |
784 *} |
787 *} |
785 |
788 |
786 local_setup %gray {* |
789 local_setup %gray {* |
787 LocalTheory.define Thm.internalK |
790 LocalTheory.define Thm.internalK |
812 also difficult to read. In the next chapter we will see how the (build in) |
815 also difficult to read. In the next chapter we will see how the (build in) |
813 antiquotation @{text "@{term \<dots>}"} can be used to construct terms. A |
816 antiquotation @{text "@{term \<dots>}"} can be used to construct terms. A |
814 restriction of this antiquotation is that it does not allow you to use |
817 restriction of this antiquotation is that it does not allow you to use |
815 schematic variables. If you want to have an antiquotation that does not have |
818 schematic variables. If you want to have an antiquotation that does not have |
816 this restriction, you can implement your own using the function @{ML_ind |
819 this restriction, you can implement your own using the function @{ML_ind |
817 ML_Antiquote.inline}. The code for the antiquotation @{text "term_pat"} is |
820 inline in ML_Antiquote}. The code for the antiquotation @{text "term_pat"} is |
818 as follows. |
821 as follows. |
819 *} |
822 *} |
820 |
823 |
821 ML %linenosgray{*let |
824 ML %linenosgray{*let |
822 val parser = Args.context -- Scan.lift Args.name_source |
825 val parser = Args.context -- Scan.lift Args.name_source |