1 (* Title: HOL/Quotient_Examples/Lift_Fun.thy
5 header {* Example of lifting definitions with contravariant or co/contravariant type variables *}
9 imports Main "~~/src/HOL/Library/Quotient_Syntax"
12 text {* This file is meant as a test case for features introduced in the changeset 2d8949268303.
13 It contains examples of lifting definitions with quotients that have contravariant
14 type variables or type variables which are covariant and contravariant in the same time. *}
16 subsection {* Contravariant type variables *}
18 text {* 'a is a contravariant type variable and we are able to map over this variable
19 in the following four definitions. This example is based on HOL/Fun.thy. *}
22 ('a, 'b) fun' (infixr "\<rightarrow>" 55) = "'a \<Rightarrow> 'b" / "op ="
23 by (simp add: identity_equivp)
25 quotient_definition "comp' :: ('b \<rightarrow> 'c) \<rightarrow> ('a \<rightarrow> 'b) \<rightarrow> 'a \<rightarrow> 'c" is
26 "comp :: ('b \<Rightarrow> 'c) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> 'a \<Rightarrow> 'c" done
28 quotient_definition "fcomp' :: ('a \<Rightarrow> 'b) \<Rightarrow> ('b \<Rightarrow> 'c) \<Rightarrow> 'a \<Rightarrow> 'c" is
31 quotient_definition "map_fun' :: ('c \<rightarrow> 'a) \<rightarrow> ('b \<rightarrow> 'd) \<rightarrow> ('a \<rightarrow> 'b) \<rightarrow> 'c \<rightarrow> 'd"
32 is "map_fun::('c \<Rightarrow> 'a) \<Rightarrow> ('b \<Rightarrow> 'd) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> 'c \<Rightarrow> 'd" done
34 quotient_definition "inj_on' :: ('a \<rightarrow> 'b) \<rightarrow> 'a set \<rightarrow> bool" is inj_on done
36 quotient_definition "bij_betw' :: ('a \<rightarrow> 'b) \<rightarrow> 'a set \<rightarrow> 'b set \<rightarrow> bool" is bij_betw done
39 subsection {* Co/Contravariant type variables *}
41 text {* 'a is a covariant and contravariant type variable in the same time.
42 The following example is a bit artificial. We haven't had a natural one yet. *}
44 quotient_type 'a endofun = "'a \<Rightarrow> 'a" / "op =" by (simp add: identity_equivp)
46 definition map_endofun' :: "('a \<Rightarrow> 'b) \<Rightarrow> ('b \<Rightarrow> 'a) \<Rightarrow> ('a => 'a) \<Rightarrow> ('b => 'b)"
47 where "map_endofun' f g e = map_fun g f e"
49 quotient_definition "map_endofun :: ('a \<Rightarrow> 'b) \<Rightarrow> ('b \<Rightarrow> 'a) \<Rightarrow> 'a endofun \<Rightarrow> 'b endofun" is
52 text {* Registration of the map function for 'a endofun. *}
54 enriched_type map_endofun : map_endofun
56 have "\<forall> x. abs_endofun (rep_endofun x) = x" using Quotient_endofun by (auto simp: Quotient_def)
57 then show "map_endofun id id = id"
58 by (auto simp: map_endofun_def map_endofun'_def map_fun_def fun_eq_iff)
60 have a:"\<forall> x. rep_endofun (abs_endofun x) = x" using Quotient_endofun
61 Quotient_rep_abs[of "(op =)" abs_endofun rep_endofun] by blast
62 show "\<And>f g h i. map_endofun f g \<circ> map_endofun h i = map_endofun (f \<circ> h) (i \<circ> g)"
63 by (auto simp: map_endofun_def map_endofun'_def map_fun_def fun_eq_iff) (simp add: a o_assoc)
66 text {* Relator for 'a endofun. *}
69 endofun_rel' :: "('a \<Rightarrow> 'b \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> bool"
71 "endofun_rel' R = (\<lambda>f g. (R ===> R) f g)"
73 quotient_definition "endofun_rel :: ('a \<Rightarrow> 'b \<Rightarrow> bool) \<Rightarrow> 'a endofun \<Rightarrow> 'b endofun \<Rightarrow> bool" is
76 lemma endofun_quotient:
77 assumes a: "Quotient R Abs Rep"
78 shows "Quotient (endofun_rel R) (map_endofun Abs Rep) (map_endofun Rep Abs)"
79 proof (intro QuotientI)
80 show "\<And>a. map_endofun Abs Rep (map_endofun Rep Abs a) = a"
81 by (metis (hide_lams, no_types) a abs_o_rep id_apply map_endofun.comp map_endofun.id o_eq_dest_lhs)
83 show "\<And>a. endofun_rel R (map_endofun Rep Abs a) (map_endofun Rep Abs a)"
84 using fun_quotient[OF a a, THEN Quotient_rep_reflp]
85 unfolding endofun_rel_def map_endofun_def map_fun_def o_def map_endofun'_def endofun_rel'_def id_def
86 by (metis (mono_tags) Quotient_endofun rep_abs_rsp)
88 have abs_to_eq: "\<And> x y. abs_endofun x = abs_endofun y \<Longrightarrow> x = y"
89 by (drule arg_cong[where f=rep_endofun]) (simp add: Quotient_rep_abs[OF Quotient_endofun])
91 show "endofun_rel R r s =
92 (endofun_rel R r r \<and>
93 endofun_rel R s s \<and> map_endofun Abs Rep r = map_endofun Abs Rep s)"
94 apply(auto simp add: endofun_rel_def endofun_rel'_def map_endofun_def map_endofun'_def)
95 using fun_quotient[OF a a,THEN Quotient_refl1]
97 using fun_quotient[OF a a,THEN Quotient_refl2]
99 using fun_quotient[OF a a, THEN Quotient_rel]
101 by (auto intro: fun_quotient[OF a a, THEN Quotient_rel, THEN iffD1] simp add: abs_to_eq)
104 declare [[map endofun = (endofun_rel, endofun_quotient)]]
106 quotient_definition "endofun_id_id :: ('a endofun) endofun" is "id :: ('a \<Rightarrow> 'a) \<Rightarrow> ('a \<Rightarrow> 'a)" done
109 thm endofun_id_id_def
111 quotient_type 'a endofun' = "'a endofun" / "op =" by (simp add: identity_equivp)
113 text {* We have to map "'a endofun" to "('a endofun') endofun", i.e., mapping (lifting)
114 over a type variable which is a covariant and contravariant type variable. *}
116 quotient_definition "endofun'_id_id :: ('a endofun') endofun'" is endofun_id_id done
119 thm endofun'_id_id_def