# HG changeset patch # User wenzelm # Date 971904553 -7200 # Node ID ca93fe25a84bac9969643c5cec7bbce52c7d3757 # Parent e4d13d8a90118792152317964dc8920ce3129fa6 Quotient types; diff -r e4d13d8a9011 -r ca93fe25a84b src/HOL/Library/Quotient.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Library/Quotient.thy Wed Oct 18 23:29:13 2000 +0200 @@ -0,0 +1,313 @@ +(* Title: HOL/Library/Quotient.thy + ID: $Id$ + Author: Gertrud Bauer and Markus Wenzel, TU Muenchen +*) + +header {* + \title{Quotients} + \author{Gertrud Bauer and Markus Wenzel} +*} + +theory Quotient = Main: + +text {* + Higher-order quotients are defined over partial equivalence relations + (PERs) instead of total ones. We provide axiomatic type classes + @{text "equiv < partial_equiv"} and a type constructor + @{text "'a quot"} with basic operations. Note that conventional + quotient constructions emerge as a special case. This development is + loosely based on \cite{Slotosch:1997}. +*} + + +subsection {* Equivalence relations *} + +subsubsection {* Partial equivalence *} + +text {* + Type class @{text partial_equiv} models partial equivalence relations + (PERs) using the polymorphic @{text "\ :: 'a => 'a => bool"} relation, + which is required to be symmetric and transitive, but not necessarily + reflexive. +*} + +consts + eqv :: "'a => 'a => bool" (infixl "\" 50) + +axclass partial_equiv < "term" + eqv_sym [elim?]: "x \ y ==> y \ x" + eqv_trans [trans]: "x \ y ==> y \ z ==> x \ z" + +text {* + \medskip The domain of a partial equivalence relation is the set of + reflexive elements. Due to symmetry and transitivity this + characterizes exactly those elements that are connected with + \emph{any} other one. +*} + +constdefs + domain :: "'a::partial_equiv set" + "domain == {x. x \ x}" + +lemma domainI [intro]: "x \ x ==> x \ domain" + by (unfold domain_def) blast + +lemma domainD [dest]: "x \ domain ==> x \ x" + by (unfold domain_def) blast + +theorem domainI' [elim?]: "x \ y ==> x \ domain" +proof + assume xy: "x \ y" + also from xy have "y \ x" .. + finally show "x \ x" . +qed + + +subsubsection {* Equivalence on function spaces *} + +text {* + The @{text \} relation is lifted to function spaces. It is + important to note that this is \emph{not} the direct product, but a + structural one corresponding to the congruence property. +*} + +defs (overloaded) + eqv_fun_def: "f \ g == \x \ domain. \y \ domain. x \ y --> f x \ g y" + +lemma partial_equiv_funI [intro?]: + "(!!x y. x \ domain ==> y \ domain ==> x \ y ==> f x \ g y) ==> f \ g" + by (unfold eqv_fun_def) blast + +lemma partial_equiv_funD [dest?]: + "f \ g ==> x \ domain ==> y \ domain ==> x \ y ==> f x \ g y" + by (unfold eqv_fun_def) blast + +text {* + The class of partial equivalence relations is closed under function + spaces (in \emph{both} argument positions). +*} + +instance fun :: (partial_equiv, partial_equiv) partial_equiv +proof intro_classes + fix f g h :: "'a::partial_equiv => 'b::partial_equiv" + assume fg: "f \ g" + show "g \ f" + proof + fix x y :: 'a + assume x: "x \ domain" and y: "y \ domain" + assume "x \ y" hence "y \ x" .. + with fg y x have "f y \ g x" .. + thus "g x \ f y" .. + qed + assume gh: "g \ h" + show "f \ h" + proof + fix x y :: 'a + assume x: "x \ domain" and y: "y \ domain" and "x \ y" + with fg have "f x \ g y" .. + also from y have "y \ y" .. + with gh y y have "g y \ h y" .. + finally show "f x \ h y" . + qed +qed + + +subsubsection {* Total equivalence *} + +text {* + The class of total equivalence relations on top of PERs. It + coincides with the standard notion of equivalence, i.e.\ + @{text "\ :: 'a => 'a => bool"} is required to be reflexive, transitive + and symmetric. +*} + +axclass equiv < partial_equiv + eqv_refl [intro]: "x \ x" + +text {* + On total equivalences all elements are reflexive, and congruence + holds unconditionally. +*} + +theorem equiv_domain [intro]: "(x::'a::equiv) \ domain" +proof + show "x \ x" .. +qed + +theorem equiv_cong [dest?]: "f \ g ==> x \ y ==> f x \ g (y::'a::equiv)" +proof - + assume "f \ g" + moreover have "x \ domain" .. + moreover have "y \ domain" .. + moreover assume "x \ y" + ultimately show ?thesis .. +qed + + +subsection {* Quotient types *} + +subsubsection {* General quotients and equivalence classes *} + +text {* + The quotient type @{text "'a quot"} consists of all \emph{equivalence + classes} over elements of the base type @{typ 'a}. +*} + +typedef 'a quot = "{{x. a \ x}| a::'a. True}" + by blast + +lemma quotI [intro]: "{x. a \ x} \ quot" + by (unfold quot_def) blast + +lemma quotE [elim]: "R \ quot ==> (!!a. R = {x. a \ x} ==> C) ==> C" + by (unfold quot_def) blast + + +text {* + \medskip Standard properties of type-definitions.\footnote{(FIXME) + Better incorporate these into the typedef package?} +*} + +theorem Rep_quot_inject: "(Rep_quot x = Rep_quot y) = (x = y)" +proof + assume "Rep_quot x = Rep_quot y" + hence "Abs_quot (Rep_quot x) = Abs_quot (Rep_quot y)" by (simp only:) + thus "x = y" by (simp only: Rep_quot_inverse) +next + assume "x = y" + thus "Rep_quot x = Rep_quot y" by simp +qed + +theorem Abs_quot_inject: + "x \ quot ==> y \ quot ==> (Abs_quot x = Abs_quot y) = (x = y)" +proof + assume "Abs_quot x = Abs_quot y" + hence "Rep_quot (Abs_quot x) = Rep_quot (Abs_quot y)" by simp + also assume "x \ quot" hence "Rep_quot (Abs_quot x) = x" by (rule Abs_quot_inverse) + also assume "y \ quot" hence "Rep_quot (Abs_quot y) = y" by (rule Abs_quot_inverse) + finally show "x = y" . +next + assume "x = y" + thus "Abs_quot x = Abs_quot y" by simp +qed + +theorem Rep_quot_induct: "y \ quot ==> (!!x. P (Rep_quot x)) ==> P y" +proof - + assume "!!x. P (Rep_quot x)" hence "P (Rep_quot (Abs_quot y))" . + also assume "y \ quot" hence "Rep_quot (Abs_quot y) = y" by (rule Abs_quot_inverse) + finally show "P y" . +qed + +theorem Abs_quot_induct: "(!!y. y \ quot ==> P (Abs_quot y)) ==> P x" +proof - + assume r: "!!y. y \ quot ==> P (Abs_quot y)" + have "Rep_quot x \ quot" by (rule Rep_quot) + hence "P (Abs_quot (Rep_quot x))" by (rule r) + also have "Abs_quot (Rep_quot x) = x" by (rule Rep_quot_inverse) + finally show "P x" . +qed + +text {* + \medskip Abstracted equivalence classes are the canonical + representation of elements of a quotient type. +*} + +constdefs + eqv_class :: "('a::partial_equiv) => 'a quot" ("\_\") + "\a\ == Abs_quot {x. a \ x}" + +theorem quot_rep: "\a. A = \a\" +proof (unfold eqv_class_def) + show "\a. A = Abs_quot {x. a \ x}" + proof (induct A rule: Abs_quot_induct) + fix R assume "R \ quot" + hence "\a. R = {x. a \ x}" by blast + thus "\a. Abs_quot R = Abs_quot {x. a \ x}" by blast + qed +qed + +lemma quot_cases [case_names rep, cases type: quot]: + "(!!a. A = \a\ ==> C) ==> C" + by (insert quot_rep) blast + + +subsubsection {* Equality on quotients *} + +text {* + Equality of canonical quotient elements corresponds to the original + relation as follows. +*} + +theorem eqv_class_eqI [intro]: "a \ b ==> \a\ = \b\" +proof - + assume ab: "a \ b" + have "{x. a \ x} = {x. b \ x}" + proof (rule Collect_cong) + fix x show "(a \ x) = (b \ x)" + proof + from ab have "b \ a" .. + also assume "a \ x" + finally show "b \ x" . + next + note ab + also assume "b \ x" + finally show "a \ x" . + qed + qed + thus ?thesis by (simp only: eqv_class_def) +qed + +theorem eqv_class_eqD' [dest?]: "\a\ = \b\ ==> a \ domain ==> a \ b" (* FIXME [dest] would cause trouble with blast due to overloading *) +proof (unfold eqv_class_def) + assume "Abs_quot {x. a \ x} = Abs_quot {x. b \ x}" + hence "{x. a \ x} = {x. b \ x}" by (simp only: Abs_quot_inject quotI) + moreover assume "a \ domain" hence "a \ a" .. + ultimately have "a \ {x. b \ x}" by blast + hence "b \ a" by blast + thus "a \ b" .. +qed + +theorem eqv_class_eqD [dest?]: "\a\ = \b\ ==> a \ (b::'a::equiv)" (* FIXME [dest] would cause trouble with blast due to overloading *) +proof (rule eqv_class_eqD') + show "a \ domain" .. +qed + +lemma eqv_class_eq' [simp]: "a \ domain ==> (\a\ = \b\) = (a \ b)" + by (insert eqv_class_eqI eqv_class_eqD') blast + +lemma eqv_class_eq [simp]: "(\a\ = \b\) = (a \ (b::'a::equiv))" + by (insert eqv_class_eqI eqv_class_eqD) blast + + +subsubsection {* Picking representing elements *} + +constdefs + pick :: "'a::partial_equiv quot => 'a" + "pick A == SOME a. A = \a\" + +theorem pick_eqv' [intro?, simp]: "a \ domain ==> pick \a\ \ a" (* FIXME [intro] !? *) +proof (unfold pick_def) + assume a: "a \ domain" + show "(SOME x. \a\ = \x\) \ a" + proof (rule someI2) + show "\a\ = \a\" .. + fix x assume "\a\ = \x\" + hence "a \ x" .. + thus "x \ a" .. + qed +qed + +theorem pick_eqv [intro, simp]: "pick \a\ \ (a::'a::equiv)" +proof (rule pick_eqv') + show "a \ domain" .. +qed + +theorem pick_inverse: "\pick A\ = (A::'a::equiv quot)" (* FIXME tune proof *) +proof (cases A) + fix a assume a: "A = \a\" + hence "pick A \ a" by (simp only: pick_eqv) + hence "\pick A\ = \a\" by simp + with a show ?thesis by simp +qed + +end