663 theorem |
662 theorem |
664 assumes a: "t \<Down> t'" |
663 assumes a: "t \<Down> t'" |
665 shows "<t, []> \<mapsto>* <t', []>" |
664 shows "<t, []> \<mapsto>* <t', []>" |
666 using a |
665 using a |
667 proof (induct) |
666 proof (induct) |
668 case (e_Lam x t) |
667 case (e_Lam x t) |
669 (* no assumptions *) |
668 -- {* no assumptions *} |
670 show "<Lam [x].t, []> \<mapsto>* <Lam [x].t, []>" sorry |
669 show "<Lam [x].t, []> \<mapsto>* <Lam [x].t, []>" sorry |
671 next |
670 next |
672 case (e_App t1 x t t2 v' v) |
671 case (e_App t1 x t t2 v' v) |
673 (* all assumptions in this case *) |
672 -- {* all assumptions in this case *} |
674 have a1: "t1 \<Down> Lam [x].t" by fact |
673 have a1: "t1 \<Down> Lam [x].t" by fact |
675 have ih1: "<t1, []> \<mapsto>* <Lam [x].t, []>" by fact |
674 have ih1: "<t1, []> \<mapsto>* <Lam [x].t, []>" by fact |
676 have a2: "t2 \<Down> v'" by fact |
675 have a2: "t2 \<Down> v'" by fact |
677 have ih2: "<t2, []> \<mapsto>* <v', []>" by fact |
676 have ih2: "<t2, []> \<mapsto>* <v', []>" by fact |
678 have a3: "t[x::=v'] \<Down> v" by fact |
677 have a3: "t[x::=v'] \<Down> v" by fact |
679 have ih3: "<t[x::=v'], []> \<mapsto>* <v, []>" by fact |
678 have ih3: "<t[x::=v'], []> \<mapsto>* <v, []>" by fact |
680 (* your details *) |
679 -- {* your reasoning *} |
681 show "<App t1 t2, []> \<mapsto>* <v, []>" sorry |
680 show "<App t1 t2, []> \<mapsto>* <v, []>" sorry |
682 qed |
681 qed |
683 |
682 |
684 text {* |
683 text {* |
685 Again the automatic tools in Isabelle can discharge automatically |
684 Again the automatic tools in Isabelle can discharge automatically |
686 of the routine work in these proofs. We can write: *} |
685 of the routine work in these proofs. We can write: |
|
686 *} |
687 |
687 |
688 theorem eval_implies_machines_ctx: |
688 theorem eval_implies_machines_ctx: |
689 assumes a: "t \<Down> t'" |
689 assumes a: "t \<Down> t'" |
690 shows "<t, Es> \<mapsto>* <t', Es>" |
690 shows "<t, Es> \<mapsto>* <t', Es>" |
691 using a |
691 using a |
695 corollary eval_implies_machines: |
695 corollary eval_implies_machines: |
696 assumes a: "t \<Down> t'" |
696 assumes a: "t \<Down> t'" |
697 shows "<t, []> \<mapsto>* <t', []>" |
697 shows "<t, []> \<mapsto>* <t', []>" |
698 using a eval_implies_machines_ctx by simp |
698 using a eval_implies_machines_ctx by simp |
699 |
699 |
|
700 section {* Types *} |
700 |
701 |
701 nominal_datatype ty = |
702 nominal_datatype ty = |
702 tVar "string" |
703 tVar "string" |
703 | tArr "ty" "ty" ("_ \<rightarrow> _" [100, 100] 100) |
704 | tArr "ty" "ty" ("_ \<rightarrow> _" [100, 100] 100) |
704 |
705 |
705 |
706 |
706 text {* |
707 text {* |
707 Having defined them as nominal datatypes gives us additional |
708 Having defined them as nominal datatypes gives us additional |
708 definitions and theorems that come with types (see below). |
709 definitions and theorems that come with types (see below). |
709 *} |
710 |
710 |
|
711 text {* |
|
712 We next define the type of typing contexts, a predicate that |
711 We next define the type of typing contexts, a predicate that |
713 defines valid contexts (i.e. lists that contain only unique |
712 defines valid contexts (i.e. lists that contain only unique |
714 variables) and the typing judgement. |
713 variables) and the typing judgement. |
715 |
714 |
716 *} |
715 *} |
717 |
716 |
718 type_synonym ty_ctx = "(name \<times> ty) list" |
717 type_synonym ty_ctx = "(name \<times> ty) list" |
|
718 |
719 |
719 |
720 inductive |
720 inductive |
721 valid :: "ty_ctx \<Rightarrow> bool" |
721 valid :: "ty_ctx \<Rightarrow> bool" |
722 where |
722 where |
723 v1[intro]: "valid []" |
723 v1[intro]: "valid []" |
724 | v2[intro]: "\<lbrakk>valid \<Gamma>; atom x \<sharp> \<Gamma>\<rbrakk>\<Longrightarrow> valid ((x, T) # \<Gamma>)" |
724 | v2[intro]: "\<lbrakk>valid \<Gamma>; atom x \<sharp> \<Gamma>\<rbrakk>\<Longrightarrow> valid ((x, T) # \<Gamma>)" |
|
725 |
725 |
726 |
726 inductive |
727 inductive |
727 typing :: "ty_ctx \<Rightarrow> lam \<Rightarrow> ty \<Rightarrow> bool" ("_ \<turnstile> _ : _" [60, 60, 60] 60) |
728 typing :: "ty_ctx \<Rightarrow> lam \<Rightarrow> ty \<Rightarrow> bool" ("_ \<turnstile> _ : _" [60, 60, 60] 60) |
728 where |
729 where |
729 t_Var[intro]: "\<lbrakk>valid \<Gamma>; (x, T) \<in> set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Var x : T" |
730 t_Var[intro]: "\<lbrakk>valid \<Gamma>; (x, T) \<in> set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Var x : T" |
730 | t_App[intro]: "\<lbrakk>\<Gamma> \<turnstile> t1 : T1 \<rightarrow> T2; \<Gamma> \<turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> App t1 t2 : T2" |
731 | t_App[intro]: "\<lbrakk>\<Gamma> \<turnstile> t1 : T1 \<rightarrow> T2; \<Gamma> \<turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> App t1 t2 : T2" |
731 | t_Lam[intro]: "\<lbrakk>atom x \<sharp> \<Gamma>; (x, T1) # \<Gamma> \<turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Lam [x].t : T1 \<rightarrow> T2" |
732 | t_Lam[intro]: "\<lbrakk>atom x \<sharp> \<Gamma>; (x, T1) # \<Gamma> \<turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Lam [x].t : T1 \<rightarrow> T2" |
732 |
733 |
733 |
734 |
734 text {* |
735 text {* |
735 The predicate x \<sharp> \<Gamma>, read as x fresh for \<Gamma>, is defined by Nominal Isabelle. |
736 The predicate atom x \<sharp> \<Gamma>, read as x fresh for \<Gamma>, is defined by |
736 Freshness is defined for lambda-terms, products, lists etc. For example |
737 Nominal Isabelle. Freshness is defined for lambda-terms, products, |
737 we have: |
738 lists etc. For example we have: |
738 *} |
739 *} |
739 |
740 |
740 lemma |
741 lemma |
741 fixes x::"name" |
742 fixes x::"name" |
742 shows "atom x \<sharp> Lam [x].t" |
743 shows "atom x \<sharp> Lam [x].t" |
797 have a0: "atom x \<sharp> \<Gamma>1" by fact |
798 have a0: "atom x \<sharp> \<Gamma>1" by fact |
798 have a1: "valid \<Gamma>2" by fact |
799 have a1: "valid \<Gamma>2" by fact |
799 have a2: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
800 have a2: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
800 |
801 |
801 show "\<Gamma>2 \<turnstile> Lam [x].t : T1 \<rightarrow> T2" sorry |
802 show "\<Gamma>2 \<turnstile> Lam [x].t : T1 \<rightarrow> T2" sorry |
802 qed (auto) |
803 qed (auto) -- {* the application case *} |
803 |
804 |
804 |
805 |
805 text {* |
806 text {* |
806 Despite the frequent claim that the weakening lemma is trivial, |
807 Despite the frequent claim that the weakening lemma is trivial, |
807 routine or obvious, the proof in the lambda-case does not go |
808 routine or obvious, the proof in the lambda-case does not go |
808 smoothly through. Painful variable renamings seem to be necessary. |
809 through smoothly. Painful variable renamings seem to be necessary. |
809 But the proof using renamings is horribly complicated. It is really |
810 But the proof using renamings is horribly complicated (see below). |
810 interesting whether people who claim this proof is trivial, routine |
|
811 or obvious had this proof in mind. |
|
812 |
|
813 BTW: The following two commands help already with showing that validity |
|
814 and typing are invariant under variable (permutative) renamings. |
|
815 *} |
811 *} |
816 |
812 |
817 equivariance valid |
813 equivariance valid |
818 equivariance typing |
814 equivariance typing |
819 |
815 |
820 lemma not_to_be_tried_at_home_weakening: |
816 lemma weakening_NOT_TO_BE_TRIED_AT_HOME: |
821 assumes a: "\<Gamma>1 \<turnstile> t : T" |
817 assumes a: "\<Gamma>1 \<turnstile> t : T" |
822 and b: "valid \<Gamma>2" |
818 and b: "valid \<Gamma>2" |
823 and c: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" |
819 and c: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" |
824 shows "\<Gamma>2 \<turnstile> t : T" |
820 shows "\<Gamma>2 \<turnstile> t : T" |
825 using a b c |
821 using a b c |
826 proof (induct arbitrary: \<Gamma>2) |
822 proof (induct arbitrary: \<Gamma>2) |
827 case (t_Lam x \<Gamma>1 T1 t T2) (* lambda case *) |
823 -- {* lambda case *} |
|
824 case (t_Lam x \<Gamma>1 T1 t T2) |
828 have fc0: "atom x \<sharp> \<Gamma>1" by fact |
825 have fc0: "atom x \<sharp> \<Gamma>1" by fact |
829 have ih: "\<And>\<Gamma>3. \<lbrakk>valid \<Gamma>3; (x, T1) # \<Gamma>1 \<sqsubseteq> \<Gamma>3\<rbrakk> \<Longrightarrow> \<Gamma>3 \<turnstile> t : T2" by fact |
826 have ih: "\<And>\<Gamma>3. \<lbrakk>valid \<Gamma>3; (x, T1) # \<Gamma>1 \<sqsubseteq> \<Gamma>3\<rbrakk> \<Longrightarrow> \<Gamma>3 \<turnstile> t : T2" by fact |
|
827 -- {* we choose a fresh variable *} |
830 obtain c::"name" where fc1: "atom c \<sharp> (x, t, \<Gamma>1, \<Gamma>2)" by (rule obtain_fresh) |
828 obtain c::"name" where fc1: "atom c \<sharp> (x, t, \<Gamma>1, \<Gamma>2)" by (rule obtain_fresh) |
831 have "Lam [c].((c \<leftrightarrow> x) \<bullet> t) = Lam [x].t" using fc1 (* we then alpha-rename the lambda-abstraction *) |
829 -- {* we alpha-rename the abstraction *} |
|
830 have "Lam [c].((c \<leftrightarrow> x) \<bullet> t) = Lam [x].t" using fc1 |
832 by (auto simp add: lam.eq_iff Abs1_eq_iff flip_def) |
831 by (auto simp add: lam.eq_iff Abs1_eq_iff flip_def) |
833 moreover |
832 moreover |
834 have "\<Gamma>2 \<turnstile> Lam [c].((c \<leftrightarrow> x) \<bullet> t) : T1 \<rightarrow> T2" (* we can then alpha-rename our original goal *) |
833 -- {* we can then alpha rename the goal *} |
|
834 have "\<Gamma>2 \<turnstile> Lam [c].((c \<leftrightarrow> x) \<bullet> t) : T1 \<rightarrow> T2" |
835 proof - |
835 proof - |
836 (* we establish (x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2) and valid ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2)) *) |
836 -- {* we need to establish |
837 have "(x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2)" |
837 * (x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2) and |
|
838 ** valid ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2)) *} |
|
839 have *: "(x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2)" |
838 proof - |
840 proof - |
839 have "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
841 have "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
840 then have "(c \<leftrightarrow> x) \<bullet> ((x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2))" using fc0 fc1 |
842 then have "(c \<leftrightarrow> x) \<bullet> ((x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2))" using fc0 fc1 |
841 by (perm_simp) (simp add: flip_fresh_fresh) |
843 by (perm_simp) (simp add: flip_fresh_fresh) |
842 then show "(x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2)" by (rule permute_boolE) |
844 then show "(x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2)" by (rule permute_boolE) |
843 qed |
845 qed |
844 moreover |
846 moreover |
845 have "valid ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2))" |
847 have **: "valid ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2))" |
846 proof - |
848 proof - |
847 have "valid \<Gamma>2" by fact |
849 have "valid \<Gamma>2" by fact |
848 then show "valid ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2))" using fc1 |
850 then show "valid ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2))" using fc1 |
849 by (auto simp add: fresh_permute_left atom_eqvt valid.eqvt) |
851 by (auto simp add: fresh_permute_left atom_eqvt valid.eqvt) |
850 qed |
852 qed |
851 (* these two facts give us by induction hypothesis the following *) |
853 -- {* these two facts give us by induction hypothesis the following *} |
852 ultimately have "(x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2) \<turnstile> t : T2" using ih by simp |
854 ultimately have "(x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2) \<turnstile> t : T2" using ih by simp |
853 (* we now apply renamings to get to our goal *) |
855 -- {* we now apply renamings to get to our goal *} |
854 then have "(c \<leftrightarrow> x) \<bullet> ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2) \<turnstile> t : T2)" by (rule permute_boolI) |
856 then have "(c \<leftrightarrow> x) \<bullet> ((x, T1) # ((c \<leftrightarrow> x) \<bullet> \<Gamma>2) \<turnstile> t : T2)" by (rule permute_boolI) |
855 then have "(c, T1) # \<Gamma>2 \<turnstile> ((c \<leftrightarrow> x) \<bullet> t) : T2" using fc1 |
857 then have "(c, T1) # \<Gamma>2 \<turnstile> ((c \<leftrightarrow> x) \<bullet> t) : T2" using fc1 |
856 by (perm_simp) (simp add: flip_fresh_fresh ty_fresh) |
858 by (perm_simp) (simp add: flip_fresh_fresh ty_fresh) |
857 then show "\<Gamma>2 \<turnstile> Lam [c].((c \<leftrightarrow> x) \<bullet> t) : T1 \<rightarrow> T2" using fc1 by auto |
859 then show "\<Gamma>2 \<turnstile> Lam [c].((c \<leftrightarrow> x) \<bullet> t) : T1 \<rightarrow> T2" using fc1 by auto |
858 qed |
860 qed |
859 ultimately show "\<Gamma>2 \<turnstile> Lam [x].t : T1 \<rightarrow> T2" by simp |
861 ultimately show "\<Gamma>2 \<turnstile> Lam [x].t : T1 \<rightarrow> T2" by simp |
860 qed (auto) (* var and app cases *) |
862 qed (auto) -- {* var and app cases, luckily, are automatic *} |
861 |
863 |
862 |
864 |
863 text {* |
865 text {* |
864 The remedy to the complicated proof of the weakening proof |
866 The remedy is to use a stronger induction principle that |
865 shown above is to use a stronger induction principle that |
867 has the usual "variable convention" already build in. The |
866 has the usual variable convention already build in. The |
|
867 following command derives this induction principle for us. |
868 following command derives this induction principle for us. |
868 (We shall explain what happens here later.) |
869 (We shall explain what happens here later.) |
869 |
|
870 *} |
870 *} |
871 |
871 |
872 nominal_inductive typing |
872 nominal_inductive typing |
873 avoids t_Lam: "x" |
873 avoids t_Lam: "x" |
874 unfolding fresh_star_def |
874 unfolding fresh_star_def |
875 by (simp_all add: fresh_Pair lam.fresh ty_fresh) |
875 by (simp_all add: fresh_Pair lam.fresh ty_fresh) |
876 |
876 |
877 text {* Compare the two induction principles *} |
877 text {* Compare the two induction principles *} |
|
878 |
878 thm typing.induct |
879 thm typing.induct |
879 thm typing.strong_induct |
880 thm typing.strong_induct -- {* has the additional assumption {atom x} \<sharp> c *} |
880 |
881 |
881 text {* |
882 text {* |
882 We can use the stronger induction principle by replacing |
883 We can use the stronger induction principle by replacing |
883 the line |
884 the line |
884 |
885 |
885 proof (induct arbitrary: \<Gamma>2) |
886 proof (induct arbitrary: \<Gamma>2) |
886 |
887 |
887 with |
888 with |
888 |
889 |
889 proof (nominal_induct avoiding: \<Gamma>2 rule: typing.strong_induct) |
890 proof (nominal_induct avoiding: \<Gamma>2 rule: typing.strong_induct) |
890 |
891 |
891 Try now the proof. |
892 Try now the proof. |
892 |
|
893 *} |
893 *} |
894 |
894 |
895 |
895 |
896 lemma weakening: |
896 lemma weakening: |
897 assumes a: "\<Gamma>1 \<turnstile> t : T" |
897 assumes a: "\<Gamma>1 \<turnstile> t : T" |
898 and b: "valid \<Gamma>2" |
898 and b: "valid \<Gamma>2" |
899 and c: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" |
899 and c: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" |
900 shows "\<Gamma>2 \<turnstile> t : T" |
900 shows "\<Gamma>2 \<turnstile> t : T" |
901 using a b c |
901 using a b c |
902 proof (nominal_induct avoiding: \<Gamma>2 rule: typing.strong_induct) |
902 proof (nominal_induct avoiding: \<Gamma>2 rule: typing.strong_induct) |
903 case (t_Var \<Gamma>1 x T) (* variable case *) |
903 case (t_Var \<Gamma>1 x T) -- {* variable case is as before *} |
904 have "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
904 have "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
905 moreover |
905 moreover |
906 have "valid \<Gamma>2" by fact |
906 have "valid \<Gamma>2" by fact |
907 moreover |
907 moreover |
908 have "(x, T)\<in> set \<Gamma>1" by fact |
908 have "(x, T)\<in> set \<Gamma>1" by fact |
909 ultimately show "\<Gamma>2 \<turnstile> Var x : T" by auto |
909 ultimately show "\<Gamma>2 \<turnstile> Var x : T" by auto |
910 next |
910 next |
911 case (t_Lam x \<Gamma>1 T1 t T2) |
911 case (t_Lam x \<Gamma>1 T1 t T2) |
912 have vc: "atom x \<sharp> \<Gamma>2" by fact (* additional fact *) |
912 have vc: "atom x \<sharp> \<Gamma>2" by fact -- {* additional fact afforded by the stron induction *} |
913 have ih: "\<And>\<Gamma>3. \<lbrakk>valid \<Gamma>3; (x, T1) # \<Gamma>1 \<sqsubseteq> \<Gamma>3\<rbrakk> \<Longrightarrow> \<Gamma>3 \<turnstile> t : T2" by fact |
913 have ih: "\<And>\<Gamma>3. \<lbrakk>valid \<Gamma>3; (x, T1) # \<Gamma>1 \<sqsubseteq> \<Gamma>3\<rbrakk> \<Longrightarrow> \<Gamma>3 \<turnstile> t : T2" by fact |
914 have a0: "atom x \<sharp> \<Gamma>1" by fact |
914 have a0: "atom x \<sharp> \<Gamma>1" by fact |
915 have a1: "valid \<Gamma>2" by fact |
915 have a1: "valid \<Gamma>2" by fact |
916 have a2: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
916 have a2: "\<Gamma>1 \<sqsubseteq> \<Gamma>2" by fact |
917 |
917 have "valid ((x, T1) # \<Gamma>2)" using a1 vc by auto |
918 show "\<Gamma>2 \<turnstile> Lam [x].t : T1 \<rightarrow> T2" sorry |
918 moreover |
919 qed (auto) (* app case *) |
919 have "(x, T1) # \<Gamma>1 \<sqsubseteq> (x, T1) # \<Gamma>2" using a2 by auto |
920 |
920 ultimately |
921 |
921 have "(x, T1) # \<Gamma>2 \<turnstile> t : T2" using ih by simp |
922 text {***************************************************************** |
922 then show "\<Gamma>2 \<turnstile> Lam [x].t : T1 \<rightarrow> T2" using vc by auto |
923 |
923 qed (auto) -- {* app case *} |
924 Function Definitions: Filling a Lambda-Term into a Context |
924 |
925 ---------------------------------------------------------- |
925 |
926 |
926 section {* Function Definitions: Filling a Lambda-Term into a Context *} |
|
927 |
|
928 text {* |
927 Many functions over datatypes can be defined by recursion on the |
929 Many functions over datatypes can be defined by recursion on the |
928 structure. For this purpose, Isabelle provides "fun". To use it one needs |
930 structure. For this purpose, Isabelle provides "fun". To use it one needs |
929 to give a name for the function, its type, optionally some pretty-syntax |
931 to give a name for the function, its type, optionally some pretty-syntax |
930 and then some equations defining the function. Like in "inductive", |
932 and then some equations defining the function. Like in "inductive", |
931 "fun" expects that more than one such equation is separated by "|". |
933 "fun" expects that more than one such equation is separated by "|". |
932 |
|
933 *} |
934 *} |
934 |
935 |
935 fun |
936 fun |
936 filling :: "ctx \<Rightarrow> lam \<Rightarrow> lam" ("_\<lbrakk>_\<rbrakk>" [100, 100] 100) |
937 filling :: "ctx \<Rightarrow> lam \<Rightarrow> lam" ("_\<lbrakk>_\<rbrakk>" [100, 100] 100) |
937 where |
938 where |
939 | "(CAppL E t')\<lbrakk>t\<rbrakk> = App (E\<lbrakk>t\<rbrakk>) t'" |
940 | "(CAppL E t')\<lbrakk>t\<rbrakk> = App (E\<lbrakk>t\<rbrakk>) t'" |
940 | "(CAppR t' E)\<lbrakk>t\<rbrakk> = App t' (E\<lbrakk>t\<rbrakk>)" |
941 | "(CAppR t' E)\<lbrakk>t\<rbrakk> = App t' (E\<lbrakk>t\<rbrakk>)" |
941 |
942 |
942 text {* |
943 text {* |
943 After this definition Isabelle will be able to simplify |
944 After this definition Isabelle will be able to simplify |
944 statements like: *} |
945 statements like: |
|
946 *} |
945 |
947 |
946 lemma |
948 lemma |
947 shows "(CAppL \<box> (Var x))\<lbrakk>Var y\<rbrakk> = App (Var y) (Var x)" |
949 shows "(CAppL \<box> (Var x))\<lbrakk>Var y\<rbrakk> = App (Var y) (Var x)" |
948 by simp |
950 by simp |
949 |
951 |
950 |
|
951 fun |
952 fun |
952 ctx_compose :: "ctx \<Rightarrow> ctx \<Rightarrow> ctx" ("_ \<cdot> _" [101,100] 100) |
953 ctx_compose :: "ctx \<Rightarrow> ctx \<Rightarrow> ctx" ("_ \<odot> _" [99,98] 99) |
953 where |
954 where |
954 "\<box> \<cdot> E' = E'" |
955 "\<box> \<odot> E' = E'" |
955 | "(CAppL E t') \<cdot> E' = CAppL (E \<cdot> E') t'" |
956 | "(CAppL E t') \<odot> E' = CAppL (E \<odot> E') t'" |
956 | "(CAppR t' E) \<cdot> E' = CAppR t' (E \<cdot> E')" |
957 | "(CAppR t' E) \<odot> E' = CAppR t' (E \<odot> E')" |
957 |
958 |
958 fun |
959 fun |
959 ctx_composes :: "ctxs \<Rightarrow> ctx" ("_\<down>" [110] 110) |
960 ctx_composes :: "ctxs \<Rightarrow> ctx" ("_\<down>" [110] 110) |
960 where |
961 where |
961 "[]\<down> = \<box>" |
962 "[]\<down> = \<box>" |
962 | "(E # Es)\<down> = (Es\<down>) \<cdot> E" |
963 | "(E # Es)\<down> = (Es\<down>) \<odot> E" |
963 |
964 |
964 text {* |
965 text {* |
965 Notice that we not just have given a pretty syntax for the functions, but |
966 Notice that we not just have given a pretty syntax for the functions, but |
966 also some precedences..The numbers inside the [\<dots>] stand for the precedences |
967 also some precedences. The numbers inside the [\<dots>] stand for the precedences |
967 of the arguments; the one next to it the precedence of the whole term. |
968 of the arguments; the one next to it the precedence of the whole term. |
968 |
969 |
969 This means we have to write (Es1 \<cdot> Es2) \<cdot> Es3 otherwise Es1 \<cdot> Es2 \<cdot> Es3 is |
970 This means we have to write (Es1 \<odot> Es2) \<odot> Es3 otherwise Es1 \<odot> Es2 \<odot> Es3 is |
970 interpreted as Es1 \<cdot> (Es2 \<cdot> Es3). |
971 interpreted as Es1 \<odot> (Es2 \<odot> Es3). |
971 *} |
972 *} |
972 |
973 |
973 text {****************************************************************** |
974 section {* Structural Inductions over Contexts *} |
974 |
975 |
975 Structural Inductions over Contexts |
976 text {* |
976 ------------------------------------ |
|
977 |
|
978 So far we have had a look at an induction over an inductive predicate. |
977 So far we have had a look at an induction over an inductive predicate. |
979 Another important induction principle is structural inductions for |
978 Another important induction principle is structural inductions for |
980 datatypes. To illustrate structural inductions we prove some facts |
979 datatypes. To illustrate structural inductions we prove some facts |
981 about context composition, some of which we will need later on. |
980 about context composition, some of which we will need later on. |
982 |
981 *} |
983 *} |
982 |
984 |
983 subsection {* EXERCISE 5 *} |
985 text {****************************************************************** |
984 |
986 |
985 text {* Complete the proof and remove the sorries. *} |
987 5.) EXERCISE |
|
988 ------------ |
|
989 |
|
990 Complete the proof and remove the sorries. |
|
991 |
|
992 *} |
|
993 |
986 |
994 lemma ctx_compose: |
987 lemma ctx_compose: |
995 shows "(E1 \<cdot> E2)\<lbrakk>t\<rbrakk> = E1\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" |
988 shows "(E1 \<odot> E2)\<lbrakk>t\<rbrakk> = E1\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" |
996 proof (induct E1) |
989 proof (induct E1) |
997 case Hole |
990 case Hole |
998 show "\<box> \<cdot> E2\<lbrakk>t\<rbrakk> = \<box>\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" sorry |
991 show "(\<box> \<odot> E2)\<lbrakk>t\<rbrakk> = \<box>\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" sorry |
999 next |
992 next |
1000 case (CAppL E1 t') |
993 case (CAppL E1 t') |
1001 have ih: "(E1 \<cdot> E2)\<lbrakk>t\<rbrakk> = E1\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" by fact |
994 have ih: "(E1 \<odot> E2)\<lbrakk>t\<rbrakk> = E1\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" by fact |
1002 show "((CAppL E1 t') \<cdot> E2)\<lbrakk>t\<rbrakk> = (CAppL E1 t')\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" sorry |
995 show "((CAppL E1 t') \<odot> E2)\<lbrakk>t\<rbrakk> = (CAppL E1 t')\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" sorry |
1003 next |
996 next |
1004 case (CAppR t' E1) |
997 case (CAppR t' E1) |
1005 have ih: "(E1 \<cdot> E2)\<lbrakk>t\<rbrakk> = E1\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" by fact |
998 have ih: "(E1 \<odot> E2)\<lbrakk>t\<rbrakk> = E1\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" by fact |
1006 show "((CAppR t' E1) \<cdot> E2)\<lbrakk>t\<rbrakk> = (CAppR t' E1)\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" sorry |
999 show "((CAppR t' E1) \<odot> E2)\<lbrakk>t\<rbrakk> = (CAppR t' E1)\<lbrakk>E2\<lbrakk>t\<rbrakk>\<rbrakk>" sorry |
1007 qed |
1000 qed |
1008 |
1001 |
1009 lemma neut_hole: |
1002 lemma neut_hole: |
1010 shows "E \<cdot> \<box> = E" |
1003 shows "E \<odot> \<box> = E" |
1011 by (induct E) (simp_all) |
1004 by (induct E) (simp_all) |
1012 |
1005 |
1013 lemma circ_assoc: |
1006 lemma odot_assoc: |
1014 fixes E1 E2 E3::"ctx" |
1007 fixes E1 E2 E3::"ctx" |
1015 shows "(E1 \<cdot> E2) \<cdot> E3 = E1 \<cdot> (E2 \<cdot> E3)" |
1008 shows "(E1 \<odot> E2) \<odot> E3 = E1 \<odot> (E2 \<odot> E3)" |
1016 by (induct E1) (simp_all) |
1009 by (induct E1) (simp_all) |
1017 |
1010 |
1018 lemma |
1011 lemma |
1019 shows "(Es1 @ Es2)\<down> = (Es2\<down>) \<cdot> (Es1\<down>)" |
1012 shows "(Es1 @ Es2)\<down> = (Es2\<down>) \<odot> (Es1\<down>)" |
1020 proof (induct Es1) |
1013 proof (induct Es1) |
1021 case Nil |
1014 case Nil |
1022 show "([] @ Es2)\<down> = Es2\<down> \<cdot> []\<down>" sorry |
1015 show "([] @ Es2)\<down> = Es2\<down> \<odot> []\<down>" sorry |
1023 next |
1016 next |
1024 case (Cons E Es1) |
1017 case (Cons E Es1) |
1025 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<cdot> Es1\<down>" by fact |
1018 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<odot> Es1\<down>" by fact |
1026 |
1019 |
1027 show "((E # Es1) @ Es2)\<down> = Es2\<down> \<cdot> (E # Es1)\<down>" sorry |
1020 show "((E # Es1) @ Es2)\<down> = Es2\<down> \<odot> (E # Es1)\<down>" sorry |
1028 qed |
1021 qed |
1029 |
1022 |
1030 |
1023 |
1031 text {* |
1024 text {* |
1032 The last proof involves several steps of equational reasoning. |
1025 The last proof involves several steps of equational reasoning. |
1033 Isar provides some convenient means to express such equational |
1026 Isar provides some convenient means to express such equational |
1034 reasoning in a much cleaner fashion using the "also have" |
1027 reasoning in a much cleaner fashion using the "also have" |
1035 construction. *} |
1028 construction. |
|
1029 *} |
|
1030 |
1036 |
1031 |
1037 lemma |
1032 lemma |
1038 shows "(Es1 @ Es2)\<down> = (Es2\<down>) \<cdot> (Es1\<down>)" |
1033 shows "(Es1 @ Es2)\<down> = (Es2\<down>) \<odot> (Es1\<down>)" |
1039 proof (induct Es1) |
1034 proof (induct Es1) |
1040 case Nil |
1035 case Nil |
1041 show "([] @ Es2)\<down> = Es2\<down> \<cdot> []\<down>" using neut_hole by simp |
1036 show "([] @ Es2)\<down> = Es2\<down> \<odot> []\<down>" using neut_hole by simp |
1042 next |
1037 next |
1043 case (Cons E Es1) |
1038 case (Cons E Es1) |
1044 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<cdot> Es1\<down>" by fact |
1039 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<odot> Es1\<down>" by fact |
1045 have "((E # Es1) @ Es2)\<down> = (Es1 @ Es2)\<down> \<cdot> E" by simp |
1040 have "((E # Es1) @ Es2)\<down> = (Es1 @ Es2)\<down> \<odot> E" by simp |
1046 also have "\<dots> = (Es2\<down> \<cdot> Es1\<down>) \<cdot> E" using ih by simp |
1041 also have "\<dots> = (Es2\<down> \<odot> Es1\<down>) \<odot> E" using ih by simp |
1047 also have "\<dots> = Es2\<down> \<cdot> (Es1\<down> \<cdot> E)" using circ_assoc by simp |
1042 also have "\<dots> = Es2\<down> \<odot> (Es1\<down> \<odot> E)" using odot_assoc by simp |
1048 also have "\<dots> = Es2\<down> \<cdot> (E # Es1)\<down>" by simp |
1043 also have "\<dots> = Es2\<down> \<odot> (E # Es1)\<down>" by simp |
1049 finally show "((E # Es1) @ Es2)\<down> = Es2\<down> \<cdot> (E # Es1)\<down>" by simp |
1044 finally show "((E # Es1) @ Es2)\<down> = Es2\<down> \<odot> (E # Es1)\<down>" by simp |
1050 qed |
1045 qed |
1051 |
1046 |
1052 text {****************************************************************** |
1047 text {****************************************************************** |
1053 |
1048 |
1054 Formalising Barendregt's Proof of the Substitution Lemma |
1049 Formalising Barendregt's Proof of the Substitution Lemma |
1075 of such a block to the 'outside' is the implication |
1070 of such a block to the 'outside' is the implication |
1076 |
1071 |
1077 \<lbrakk>A; B\<rbrakk> \<Longrightarrow> "C" |
1072 \<lbrakk>A; B\<rbrakk> \<Longrightarrow> "C" |
1078 |
1073 |
1079 Now if we want to prove a property "smth" using the case-distinctions |
1074 Now if we want to prove a property "smth" using the case-distinctions |
1080 P\<^isub>1, P\<^isub>2 and P\<^isub>3 then we can use the following reasoning: |
1075 P1, P2 and P3 then we can use the following reasoning: |
1081 |
1076 |
1082 { assume "P\<^isub>1" |
1077 { assume "P1" |
1083 \<dots> |
1078 \<dots> |
1084 have "smth" |
1079 have "smth" |
1085 } |
1080 } |
1086 moreover |
1081 moreover |
1087 { assume "P\<^isub>2" |
1082 { assume "P2" |
1088 \<dots> |
1083 \<dots> |
1089 have "smth" |
1084 have "smth" |
1090 } |
1085 } |
1091 moreover |
1086 moreover |
1092 { assume "P\<^isub>3" |
1087 { assume "P3" |
1093 \<dots> |
1088 \<dots> |
1094 have "smth" |
1089 have "smth" |
1095 } |
1090 } |
1096 ultimately have "smth" by blast |
1091 ultimately have "smth" by blast |
1097 |
1092 |
1098 The blocks establish the implications |
1093 The blocks establish the implications |
1099 |
1094 |
1100 P\<^isub>1 \<Longrightarrow> smth |
1095 P1 \<Longrightarrow> smth |
1101 P\<^isub>2 \<Longrightarrow> smth |
1096 P2 \<Longrightarrow> smth |
1102 P\<^isub>3 \<Longrightarrow> smth |
1097 P3 \<Longrightarrow> smth |
1103 |
1098 |
1104 If we know that P\<^isub>1, P\<^isub>2 and P\<^isub>3 cover all the cases, that is P\<^isub>1 \<or> P\<^isub>2 \<or> P\<^isub>3 is |
1099 If we know that P1, P2 and P3 cover all the cases, that is P1 \<or> P2 \<or> P3 is |
1105 true, then we have 'ultimately' established the property "smth" |
1100 true, then we have 'ultimately' established the property "smth" |
1106 |
1101 |
1107 *} |
1102 *} |
1108 |
1103 |
1109 text {****************************************************************** |
1104 section {* EXERCISE 7 *} |
1110 |
1105 |
1111 7.) Exercise |
1106 text {* |
1112 ------------ |
|
1113 |
|
1114 Fill in the cases 1.2 and 1.3 and the equational reasoning |
1107 Fill in the cases 1.2 and 1.3 and the equational reasoning |
1115 in the lambda-case. |
1108 in the lambda-case. |
1116 *} |
1109 *} |
1117 |
1110 |
1118 lemma forget: |
1111 lemma forget: |
1119 shows "atom x \<sharp> t \<Longrightarrow> t[x ::= s] = t" |
1112 shows "atom x \<sharp> t \<Longrightarrow> t[x ::= s] = t" |
1120 apply(nominal_induct t avoiding: x s rule: lam.strong_induct) |
1113 by (nominal_induct t avoiding: x s rule: lam.strong_induct) |
1121 apply(auto simp add: lam.fresh fresh_at_base) |
1114 (auto simp add: lam.fresh fresh_at_base) |
1122 done |
|
1123 |
1115 |
1124 lemma fresh_fact: |
1116 lemma fresh_fact: |
1125 fixes z::"name" |
1117 fixes z::"name" |
1126 assumes a: "atom z \<sharp> s" |
1118 assumes a: "atom z \<sharp> s" |
1127 and b: "z = y \<or> atom z \<sharp> t" |
1119 and b: "z = y \<or> atom z \<sharp> t" |
1128 shows "atom z \<sharp> t[y ::= s]" |
1120 shows "atom z \<sharp> t[y ::= s]" |
1129 using a b |
1121 using a b |
1130 apply (nominal_induct t avoiding: z y s rule: lam.strong_induct) |
1122 by (nominal_induct t avoiding: z y s rule: lam.strong_induct) |
1131 apply (auto simp add: lam.fresh fresh_at_base) |
1123 (auto simp add: lam.fresh fresh_at_base) |
1132 done |
1124 |
1133 |
|
1134 thm forget |
|
1135 thm fresh_fact |
|
1136 |
1125 |
1137 lemma |
1126 lemma |
1138 assumes a: "x \<noteq> y" |
1127 assumes a: "x \<noteq> y" |
1139 and b: "atom x \<sharp> L" |
1128 and b: "atom x \<sharp> L" |
1140 shows "M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" |
1129 shows "M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" |