| author | wenzelm | 
| Sun, 07 Feb 2016 19:43:40 +0100 | |
| changeset 62271 | 4cfe65cfd369 | 
| parent 58961 | 7c507e664047 | 
| child 63167 | 0909deb8059b | 
| permissions | -rw-r--r-- | 
| 47660 | 1  | 
(* Title: HOL/Quotient_Examples/Lift_FSet.thy  | 
2  | 
Author: Brian Huffman, TU Munich  | 
|
3  | 
*)  | 
|
4  | 
||
| 58889 | 5  | 
section {* Lifting and transfer with a finite set type *}
 | 
| 47660 | 6  | 
|
7  | 
theory Lift_FSet  | 
|
| 
53013
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
8  | 
imports Main  | 
| 47660 | 9  | 
begin  | 
10  | 
||
11  | 
subsection {* Equivalence relation and quotient type definition *}
 | 
|
12  | 
||
13  | 
definition list_eq :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool"  | 
|
14  | 
where [simp]: "list_eq xs ys \<longleftrightarrow> set xs = set ys"  | 
|
15  | 
||
16  | 
lemma reflp_list_eq: "reflp list_eq"  | 
|
17  | 
unfolding reflp_def by simp  | 
|
18  | 
||
19  | 
lemma symp_list_eq: "symp list_eq"  | 
|
20  | 
unfolding symp_def by simp  | 
|
21  | 
||
22  | 
lemma transp_list_eq: "transp list_eq"  | 
|
23  | 
unfolding transp_def by simp  | 
|
24  | 
||
25  | 
lemma equivp_list_eq: "equivp list_eq"  | 
|
26  | 
by (intro equivpI reflp_list_eq symp_list_eq transp_list_eq)  | 
|
27  | 
||
| 
53013
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
28  | 
context  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
29  | 
begin  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
30  | 
interpretation lifting_syntax .  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
31  | 
|
| 
51376
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
32  | 
lemma list_eq_transfer [transfer_rule]:  | 
| 
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
33  | 
assumes [transfer_rule]: "bi_unique A"  | 
| 
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
34  | 
shows "(list_all2 A ===> list_all2 A ===> op =) list_eq list_eq"  | 
| 
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
35  | 
unfolding list_eq_def [abs_def] by transfer_prover  | 
| 
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
36  | 
|
| 
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
37  | 
quotient_type 'a fset = "'a list" / "list_eq" parametric list_eq_transfer  | 
| 47660 | 38  | 
by (rule equivp_list_eq)  | 
39  | 
||
40  | 
subsection {* Lifted constant definitions *}
 | 
|
41  | 
||
| 
58961
 
7c507e664047
dropped redundant transfer rules (now proved and registered by datatype and plugins)
 
traytel 
parents: 
58889 
diff
changeset
 | 
42  | 
lift_definition fnil :: "'a fset" ("{||}") is "[]" parametric list.ctr_transfer(1) .
 | 
| 47660 | 43  | 
|
| 
58961
 
7c507e664047
dropped redundant transfer rules (now proved and registered by datatype and plugins)
 
traytel 
parents: 
58889 
diff
changeset
 | 
44  | 
lift_definition fcons :: "'a \<Rightarrow> 'a fset \<Rightarrow> 'a fset" is Cons parametric list.ctr_transfer(2)  | 
| 47660 | 45  | 
by simp  | 
46  | 
||
| 
51376
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
47  | 
lift_definition fappend :: "'a fset \<Rightarrow> 'a fset \<Rightarrow> 'a fset" is append parametric append_transfer  | 
| 47660 | 48  | 
by simp  | 
49  | 
||
| 
58961
 
7c507e664047
dropped redundant transfer rules (now proved and registered by datatype and plugins)
 
traytel 
parents: 
58889 
diff
changeset
 | 
50  | 
lift_definition fmap :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a fset \<Rightarrow> 'b fset" is map parametric list.map_transfer
 | 
| 47660 | 51  | 
by simp  | 
52  | 
||
| 
51376
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
53  | 
lift_definition ffilter :: "('a \<Rightarrow> bool) \<Rightarrow> 'a fset \<Rightarrow> 'a fset" is filter parametric filter_transfer
 | 
| 47660 | 54  | 
by simp  | 
55  | 
||
| 
58961
 
7c507e664047
dropped redundant transfer rules (now proved and registered by datatype and plugins)
 
traytel 
parents: 
58889 
diff
changeset
 | 
56  | 
lift_definition fset :: "'a fset \<Rightarrow> 'a set" is set parametric list.set_transfer  | 
| 47660 | 57  | 
by simp  | 
58  | 
||
59  | 
text {* Constants with nested types (like concat) yield a more
 | 
|
60  | 
complicated proof obligation. *}  | 
|
61  | 
||
62  | 
lemma list_all2_cr_fset:  | 
|
63  | 
"list_all2 cr_fset xs ys \<longleftrightarrow> map abs_fset xs = ys"  | 
|
64  | 
unfolding cr_fset_def  | 
|
65  | 
apply safe  | 
|
66  | 
apply (erule list_all2_induct, simp, simp)  | 
|
67  | 
apply (simp add: list_all2_map2 List.list_all2_refl)  | 
|
68  | 
done  | 
|
69  | 
||
70  | 
lemma abs_fset_eq_iff: "abs_fset xs = abs_fset ys \<longleftrightarrow> list_eq xs ys"  | 
|
71  | 
using Quotient_rel [OF Quotient_fset] by simp  | 
|
72  | 
||
| 
51376
 
8e38ff09864a
simplify Lift_FSet because we have parametricity in Lifting now
 
kuncar 
parents: 
50227 
diff
changeset
 | 
73  | 
lift_definition fconcat :: "'a fset fset \<Rightarrow> 'a fset" is concat parametric concat_transfer  | 
| 55732 | 74  | 
proof (simp only: fset.pcr_cr_eq)  | 
| 47660 | 75  | 
fix xss yss :: "'a list list"  | 
76  | 
assume "(list_all2 cr_fset OO list_eq OO (list_all2 cr_fset)\<inverse>\<inverse>) xss yss"  | 
|
77  | 
then obtain uss vss where  | 
|
78  | 
"list_all2 cr_fset xss uss" and "list_eq uss vss" and  | 
|
79  | 
"list_all2 cr_fset yss vss" by clarsimp  | 
|
80  | 
hence "list_eq (map abs_fset xss) (map abs_fset yss)"  | 
|
81  | 
unfolding list_all2_cr_fset by simp  | 
|
82  | 
thus "list_eq (concat xss) (concat yss)"  | 
|
83  | 
apply (simp add: set_eq_iff image_def)  | 
|
84  | 
apply safe  | 
|
85  | 
apply (rename_tac xs, drule_tac x="abs_fset xs" in spec)  | 
|
86  | 
apply (drule iffD1, fast, clarsimp simp add: abs_fset_eq_iff, fast)  | 
|
87  | 
apply (rename_tac xs, drule_tac x="abs_fset xs" in spec)  | 
|
88  | 
apply (drule iffD2, fast, clarsimp simp add: abs_fset_eq_iff, fast)  | 
|
89  | 
done  | 
|
90  | 
qed  | 
|
91  | 
||
| 
53013
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
92  | 
lemma member_transfer:  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
93  | 
assumes [transfer_rule]: "bi_unique A"  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
94  | 
shows "(A ===> list_all2 A ===> op=) (\<lambda>x xs. x \<in> set xs) (\<lambda>x xs. x \<in> set xs)"  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
95  | 
by transfer_prover  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
96  | 
|
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
97  | 
end  | 
| 
 
3fbcfa911863
remove unnecessary dependencies on Library/Quotient_*
 
kuncar 
parents: 
52354 
diff
changeset
 | 
98  | 
|
| 
51410
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
99  | 
syntax  | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
100  | 
  "_insert_fset"     :: "args => 'a fset"  ("{|(_)|}")
 | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
101  | 
|
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
102  | 
translations  | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
103  | 
  "{|x, xs|}" == "CONST fcons x {|xs|}"
 | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
104  | 
  "{|x|}"     == "CONST fcons x {||}"
 | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
105  | 
|
| 
51411
 
deb59caefdb3
rename fset_member to fmember and prove parametricity
 
kuncar 
parents: 
51410 
diff
changeset
 | 
106  | 
lift_definition fmember :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" (infix "|\<in>|" 50) is "\<lambda>x xs. x \<in> set xs"  | 
| 
 
deb59caefdb3
rename fset_member to fmember and prove parametricity
 
kuncar 
parents: 
51410 
diff
changeset
 | 
107  | 
parametric member_transfer by simp  | 
| 
51410
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
108  | 
|
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
109  | 
abbreviation notin_fset :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" (infix "|\<notin>|" 50) where  | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
110  | 
"x |\<notin>| S \<equiv> \<not> (x |\<in>| S)"  | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
111  | 
|
| 
51411
 
deb59caefdb3
rename fset_member to fmember and prove parametricity
 
kuncar 
parents: 
51410 
diff
changeset
 | 
112  | 
lemma fmember_fmap[simp]: "a |\<in>| fmap f X = (\<exists>b. b |\<in>| X \<and> a = f b)"  | 
| 
51410
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
113  | 
by transfer auto  | 
| 
 
f0865a641e76
BNF uses fset defined via Lifting/Transfer rather than Quotient
 
traytel 
parents: 
51376 
diff
changeset
 | 
114  | 
|
| 
47937
 
70375fa2679d
generate abs_eq, use it as a code equation for total quotients; no_abs_code renamed to no_code; added no_code for quotient_type command
 
kuncar 
parents: 
47676 
diff
changeset
 | 
115  | 
text {* We can export code: *}
 | 
| 
 
70375fa2679d
generate abs_eq, use it as a code equation for total quotients; no_abs_code renamed to no_code; added no_code for quotient_type command
 
kuncar 
parents: 
47676 
diff
changeset
 | 
116  | 
|
| 
51411
 
deb59caefdb3
rename fset_member to fmember and prove parametricity
 
kuncar 
parents: 
51410 
diff
changeset
 | 
117  | 
export_code fnil fcons fappend fmap ffilter fset fmember in SML  | 
| 
47937
 
70375fa2679d
generate abs_eq, use it as a code equation for total quotients; no_abs_code renamed to no_code; added no_code for quotient_type command
 
kuncar 
parents: 
47676 
diff
changeset
 | 
118  | 
|
| 47660 | 119  | 
subsection {* Using transfer with type @{text "fset"} *}
 | 
120  | 
||
121  | 
text {* The correspondence relation @{text "cr_fset"} can only relate
 | 
|
122  | 
  @{text "list"} and @{text "fset"} types with the same element type.
 | 
|
123  | 
  To relate nested types like @{text "'a list list"} and
 | 
|
124  | 
  @{text "'a fset fset"}, we define a parameterized version of the
 | 
|
| 50227 | 125  | 
  correspondence relation, @{text "pcr_fset"}. *}
 | 
126  | 
||
127  | 
thm pcr_fset_def  | 
|
| 47660 | 128  | 
|
129  | 
subsection {* Transfer examples *}
 | 
|
130  | 
||
131  | 
text {* The @{text "transfer"} method replaces equality on @{text
 | 
|
132  | 
  "fset"} with the @{text "list_eq"} relation on lists, which is
 | 
|
133  | 
logically equivalent. *}  | 
|
134  | 
||
135  | 
lemma "fmap f (fmap g xs) = fmap (f \<circ> g) xs"  | 
|
136  | 
apply transfer  | 
|
137  | 
apply simp  | 
|
138  | 
done  | 
|
139  | 
||
140  | 
text {* The @{text "transfer'"} variant can replace equality on @{text
 | 
|
141  | 
  "fset"} with equality on @{text "list"}, which is logically stronger
 | 
|
142  | 
but sometimes more convenient. *}  | 
|
143  | 
||
144  | 
lemma "fmap f (fmap g xs) = fmap (f \<circ> g) xs"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
145  | 
using map_map [Transfer.transferred] .  | 
| 47660 | 146  | 
|
147  | 
lemma "ffilter p (fmap f xs) = fmap f (ffilter (p \<circ> f) xs)"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
148  | 
using filter_map [Transfer.transferred] .  | 
| 47660 | 149  | 
|
150  | 
lemma "ffilter p (ffilter q xs) = ffilter (\<lambda>x. q x \<and> p x) xs"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
151  | 
using filter_filter [Transfer.transferred] .  | 
| 47660 | 152  | 
|
153  | 
lemma "fset (fcons x xs) = insert x (fset xs)"  | 
|
| 
57816
 
d8bbb97689d3
no need for 'set_simps' now that 'datatype_new' generates the desired 'set' property
 
blanchet 
parents: 
55732 
diff
changeset
 | 
154  | 
using list.set(2) [Transfer.transferred] .  | 
| 47660 | 155  | 
|
156  | 
lemma "fset (fappend xs ys) = fset xs \<union> fset ys"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
157  | 
using set_append [Transfer.transferred] .  | 
| 47660 | 158  | 
|
159  | 
lemma "fset (fconcat xss) = (\<Union>xs\<in>fset xss. fset xs)"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
160  | 
using set_concat [Transfer.transferred] .  | 
| 47660 | 161  | 
|
162  | 
lemma "\<forall>x\<in>fset xs. f x = g x \<Longrightarrow> fmap f xs = fmap g xs"  | 
|
163  | 
apply transfer  | 
|
164  | 
apply (simp cong: map_cong del: set_map)  | 
|
165  | 
done  | 
|
166  | 
||
167  | 
lemma "fnil = fconcat xss \<longleftrightarrow> (\<forall>xs\<in>fset xss. xs = fnil)"  | 
|
168  | 
apply transfer  | 
|
169  | 
apply simp  | 
|
170  | 
done  | 
|
171  | 
||
172  | 
lemma "fconcat (fmap (\<lambda>x. fcons x fnil) xs) = xs"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
173  | 
apply transfer  | 
| 47660 | 174  | 
apply simp  | 
175  | 
done  | 
|
176  | 
||
177  | 
lemma concat_map_concat: "concat (map concat xsss) = concat (concat xsss)"  | 
|
178  | 
by (induct xsss, simp_all)  | 
|
179  | 
||
180  | 
lemma "fconcat (fmap fconcat xss) = fconcat (fconcat xss)"  | 
|
| 
52354
 
acb4f932dd24
implement 'transferred' attribute for transfer package, with support for monotonicity of !!/==>
 
huffman 
parents: 
51994 
diff
changeset
 | 
181  | 
using concat_map_concat [Transfer.transferred] .  | 
| 47660 | 182  | 
|
183  | 
end  |