Mercurial > cpdt > repo
comparison src/Large.v @ 462:d7a73ab1df7b
Proofreading pass through Chapter 16
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 29 Aug 2012 16:33:59 -0400 |
parents | 980962258b49 |
children | 1fd4109f7b31 |
comparison
equal
deleted
inserted
replaced
461:b6c47e6d43dc | 462:d7a73ab1df7b |
---|---|
154 induction e as [ | ? IHe1 ? IHe2 ]; [ | 154 induction e as [ | ? IHe1 ? IHe2 ]; [ |
155 trivial | 155 trivial |
156 | simpl; rewrite IHe1; rewrite IHe2; rewrite mult_plus_distr_l; trivial ]. | 156 | simpl; rewrite IHe1; rewrite IHe2; rewrite mult_plus_distr_l; trivial ]. |
157 Qed. | 157 Qed. |
158 | 158 |
159 (** We use the form of the semicolon operator that allows a different tactic to be specified for each generated subgoal. This is an improvement in robustness of the script. We no longer need to worry about tactics from one case being applied to a different case. Still, the proof script is not especially readable. Probably most readers would not find it helpful in explaining why the theorem is true. | 159 (** We use the form of the semicolon operator that allows a different tactic to be specified for each generated subgoal. This is an improvement in robustness of the script. We no longer need to worry about tactics from one case being applied to a different case. Still, the proof script is not especially readable. Probably most readers would not find it helpful in explaining why the theorem is true. The same could be said for scripts which use the%\index{bullets}% _bullets_ or curly braces provided by Coq 8.4, which allow code like the above to be stepped through interactively, with periods in place of the semicolons, while representing proof structure in a way that is enforced by Coq. Interactive replay of scripts becomes easier, but readability is not really helped. |
160 | 160 |
161 The situation gets worse in considering extensions to the theorem we want to prove. Let us add multiplication nodes to our [exp] type and see how the proof fares. *) | 161 The situation gets worse in considering extensions to the theorem we want to prove. Let us add multiplication nodes to our [exp] type and see how the proof fares. *) |
162 | 162 |
163 Reset exp. | 163 Reset exp. |
164 | 164 |
639 The %\index{tactics!abstract}%[abstract] tactical helps us force thunks by proving some subgoals as their own lemmas. For instance, a proof [induction x; crush] can in many cases be made to use significantly less peak memory by changing it to [induction x; abstract crush]. The main limitation of [abstract] is that it can only be applied to subgoals that are proved completely, with no undetermined unification variables in their initial states. Still, many large automated proofs can realize vast memory savings via [abstract]. *) | 639 The %\index{tactics!abstract}%[abstract] tactical helps us force thunks by proving some subgoals as their own lemmas. For instance, a proof [induction x; crush] can in many cases be made to use significantly less peak memory by changing it to [induction x; abstract crush]. The main limitation of [abstract] is that it can only be applied to subgoals that are proved completely, with no undetermined unification variables in their initial states. Still, many large automated proofs can realize vast memory savings via [abstract]. *) |
640 | 640 |
641 | 641 |
642 (** * Modules *) | 642 (** * Modules *) |
643 | 643 |
644 (** Last chapter's examples of proof by reflection demonstrate opportunities for implementing abstract proof strategies with stronger formal guarantees than can be had with Ltac scripting. Coq's _module system_ provides another tool for more rigorous development of generic theorems. This feature is inspired by the module systems found in Standard ML%~\cite{modules}% and Objective Caml, and the discussion that follows assumes familiarity with the basics of one of those systems. | 644 (** Last chapter's examples of proof by reflection demonstrate opportunities for implementing abstract proof strategies with stronger formal guarantees than can be had with Ltac scripting. Coq's _module system_ provides another tool for more rigorous development of generic theorems. This feature is inspired by the module systems found in Standard ML%~\cite{modules}% and OCaml, and the discussion that follows assumes familiarity with the basics of one of those systems. |
645 | 645 |
646 ML modules facilitate the grouping of %\index{abstract type}%abstract types with operations over those types. Moreover, there is support for%\index{functor}% _functors_, which are functions from modules to modules. A canonical example of a functor is one that builds a data structure implementation from a module that describes a domain of keys and its associated comparison operations. | 646 ML modules facilitate the grouping of %\index{abstract type}%abstract types with operations over those types. Moreover, there is support for%\index{functor}% _functors_, which are functions from modules to modules. A canonical example of a functor is one that builds a data structure implementation from a module that describes a domain of keys and its associated comparison operations. |
647 | 647 |
648 When we add modules to a base language with dependent types, it becomes possible to use modules and functors to formalize kinds of reasoning that are common in algebra. For instance, this module signature captures the essence of the algebraic structure known as a group. A group consists of a carrier set [G], an associative binary operation [f], a left identity element [e] for [f], and an operation [i] that is a left inverse for [f].%\index{Vernacular commands!Module Type}% *) | 648 When we add modules to a base language with dependent types, it becomes possible to use modules and functors to formalize kinds of reasoning that are common in algebra. For instance, the following module signature captures the essence of the algebraic structure known as a group. A group consists of a carrier set [G], an associative binary operation [f], a left identity element [id] for [f], and an operation [i] that is a left inverse for [f].%\index{Vernacular commands!Module Type}% *) |
649 | 649 |
650 Module Type GROUP. | 650 Module Type GROUP. |
651 Parameter G : Set. | 651 Parameter G : Set. |
652 Parameter f : G -> G -> G. | 652 Parameter f : G -> G -> G. |
653 Parameter e : G. | 653 Parameter id : G. |
654 Parameter i : G -> G. | 654 Parameter i : G -> G. |
655 | 655 |
656 Axiom assoc : forall a b c, f (f a b) c = f a (f b c). | 656 Axiom assoc : forall a b c, f (f a b) c = f a (f b c). |
657 Axiom ident : forall a, f e a = a. | 657 Axiom ident : forall a, f id a = a. |
658 Axiom inverse : forall a, f (i a) a = e. | 658 Axiom inverse : forall a, f (i a) a = id. |
659 End GROUP. | 659 End GROUP. |
660 | 660 |
661 (** Many useful theorems hold of arbitrary groups. We capture some such theorem statements in another module signature.%\index{Vernacular commands!Declare Module}% *) | 661 (** Many useful theorems hold of arbitrary groups. We capture some such theorem statements in another module signature.%\index{Vernacular commands!Declare Module}% *) |
662 | 662 |
663 Module Type GROUP_THEOREMS. | 663 Module Type GROUP_THEOREMS. |
664 Declare Module M : GROUP. | 664 Declare Module M : GROUP. |
665 | 665 |
666 Axiom ident' : forall a, M.f a M.e = a. | 666 Axiom ident' : forall a, M.f a M.id = a. |
667 | 667 |
668 Axiom inverse' : forall a, M.f a (M.i a) = M.e. | 668 Axiom inverse' : forall a, M.f a (M.i a) = M.id. |
669 | 669 |
670 Axiom unique_ident : forall e', (forall a, M.f e' a = a) -> e' = M.e. | 670 Axiom unique_ident : forall id', (forall a, M.f id' a = a) -> id' = M.id. |
671 End GROUP_THEOREMS. | 671 End GROUP_THEOREMS. |
672 | 672 |
673 (** We implement generic proofs of these theorems with a functor, whose input is an arbitrary group [M]. %\index{Vernacular commands!Module}% *) | 673 (** We implement generic proofs of these theorems with a functor, whose input is an arbitrary group [M]. %\index{Vernacular commands!Module}% *) |
674 | 674 |
675 Module GroupProofs (M : GROUP) : GROUP_THEOREMS with Module M := M. | 675 Module GroupProofs (M : GROUP) : GROUP_THEOREMS with Module M := M. |
681 Import M. | 681 Import M. |
682 (** It would be inconvenient to repeat the prefix [M.] everywhere in our theorem statements and proofs, so we bring all the identifiers of [M] into the local scope unqualified. | 682 (** It would be inconvenient to repeat the prefix [M.] everywhere in our theorem statements and proofs, so we bring all the identifiers of [M] into the local scope unqualified. |
683 | 683 |
684 Now we are ready to prove the three theorems. The proofs are completely manual, which may seem ironic given the content of the previous sections! This illustrates another lesson, which is that short proof scripts that change infrequently may be worth leaving unautomated. It would take some effort to build suitable generic automation for these theorems about groups, so I stick with manual proof scripts to avoid distracting us from the main message of the section. We take the proofs from the Wikipedia page on elementary group theory. *) | 684 Now we are ready to prove the three theorems. The proofs are completely manual, which may seem ironic given the content of the previous sections! This illustrates another lesson, which is that short proof scripts that change infrequently may be worth leaving unautomated. It would take some effort to build suitable generic automation for these theorems about groups, so I stick with manual proof scripts to avoid distracting us from the main message of the section. We take the proofs from the Wikipedia page on elementary group theory. *) |
685 | 685 |
686 Theorem inverse' : forall a, f a (i a) = e. | 686 Theorem inverse' : forall a, f a (i a) = id. |
687 intro. | 687 intro. |
688 rewrite <- (ident (f a (i a))). | 688 rewrite <- (ident (f a (i a))). |
689 rewrite <- (inverse (f a (i a))) at 1. | 689 rewrite <- (inverse (f a (i a))) at 1. |
690 rewrite assoc. | 690 rewrite assoc. |
691 rewrite assoc. | 691 rewrite assoc. |
693 rewrite inverse. | 693 rewrite inverse. |
694 rewrite ident. | 694 rewrite ident. |
695 apply inverse. | 695 apply inverse. |
696 Qed. | 696 Qed. |
697 | 697 |
698 Theorem ident' : forall a, f a e = a. | 698 Theorem ident' : forall a, f a id = a. |
699 intro. | 699 intro. |
700 rewrite <- (inverse a). | 700 rewrite <- (inverse a). |
701 rewrite <- assoc. | 701 rewrite <- assoc. |
702 rewrite inverse'. | 702 rewrite inverse'. |
703 apply ident. | 703 apply ident. |
704 Qed. | 704 Qed. |
705 | 705 |
706 Theorem unique_ident : forall e', (forall a, M.f e' a = a) -> e' = M.e. | 706 Theorem unique_ident : forall id', (forall a, M.f id' a = a) -> id' = M.id. |
707 intros. | 707 intros. |
708 rewrite <- (H e). | 708 rewrite <- (H id). |
709 symmetry. | 709 symmetry. |
710 apply ident'. | 710 apply ident'. |
711 Qed. | 711 Qed. |
712 End GroupProofs. | 712 End GroupProofs. |
713 | 713 |
717 Open Scope Z_scope. | 717 Open Scope Z_scope. |
718 | 718 |
719 Module Int. | 719 Module Int. |
720 Definition G := Z. | 720 Definition G := Z. |
721 Definition f x y := x + y. | 721 Definition f x y := x + y. |
722 Definition e := 0. | 722 Definition id := 0. |
723 Definition i x := -x. | 723 Definition i x := -x. |
724 | 724 |
725 Theorem assoc : forall a b c, f (f a b) c = f a (f b c). | 725 Theorem assoc : forall a b c, f (f a b) c = f a (f b c). |
726 unfold f; crush. | 726 unfold f; crush. |
727 Qed. | 727 Qed. |
728 Theorem ident : forall a, f e a = a. | 728 Theorem ident : forall a, f id a = a. |
729 unfold f, e; crush. | 729 unfold f, id; crush. |
730 Qed. | 730 Qed. |
731 Theorem inverse : forall a, f (i a) a = e. | 731 Theorem inverse : forall a, f (i a) a = id. |
732 unfold f, i, e; crush. | 732 unfold f, i, id; crush. |
733 Qed. | 733 Qed. |
734 End Int. | 734 End Int. |
735 | 735 |
736 (** Next, we can produce integer-specific versions of the generic group theorems. *) | 736 (** Next, we can produce integer-specific versions of the generic group theorems. *) |
737 | 737 |
743 : forall e' : Int.G, (forall a : Int.G, Int.f e' a = a) -> e' = Int.e | 743 : forall e' : Int.G, (forall a : Int.G, Int.f e' a = a) -> e' = Int.e |
744 ]] | 744 ]] |
745 | 745 |
746 Projections like [Int.G] are known to be definitionally equal to the concrete values we have assigned to them, so the above theorem yields as a trivial corollary the following more natural restatement: *) | 746 Projections like [Int.G] are known to be definitionally equal to the concrete values we have assigned to them, so the above theorem yields as a trivial corollary the following more natural restatement: *) |
747 | 747 |
748 Theorem unique_ident : forall e', (forall a, e' + a = a) -> e' = 0. | 748 Theorem unique_ident : forall id', (forall a, id' + a = a) -> id' = 0. |
749 (* begin thide *) | 749 (* begin thide *) |
750 exact IntProofs.unique_ident. | 750 exact IntProofs.unique_ident. |
751 Qed. | 751 Qed. |
752 (* end thide *) | 752 (* end thide *) |
753 | 753 |
754 (** As in ML, the module system provides an effective way to structure large developments. Unlike in ML, Coq modules add no expressiveness; we can implement any module as an inhabitant of a dependent record type. It is the second-class nature of modules that makes them easier to use than dependent records in many case. Because modules may only be used in quite restricted ways, it is easier to support convenient module coding through special commands and editing modes, as the above example demonstrates. An isomorphic implementation with records would have suffered from lack of such conveniences as module subtyping and importation of the fields of a module. On the other hand, all module values must be determined statically, so modules may not be computed, e.g., within the defintions of normal functions, based on particular function parameters. *) | 754 (** As in ML, the module system provides an effective way to structure large developments. Unlike in ML, Coq modules add no expressiveness; we can implement any module as an inhabitant of a dependent record type. It is the second-class nature of modules that makes them easier to use than dependent records in many case. Because modules may only be used in quite restricted ways, it is easier to support convenient module coding through special commands and editing modes, as the above example demonstrates. An isomorphic implementation with records would have suffered from lack of such conveniences as module subtyping and importation of the fields of a module. On the other hand, all module values must be determined statically, so modules may not be computed, e.g., within the definitions of normal functions, based on particular function parameters. *) |
755 | 755 |
756 | 756 |
757 (** * Build Processes *) | 757 (** * Build Processes *) |
758 | 758 |
759 (* begin hide *) | 759 (* begin hide *) |