paulson@13586: (* Title: HOL/Library/FuncSet.thy paulson@13586: ID: $Id$ paulson@13586: Author: Florian Kammueller and Lawrence C Paulson paulson@13586: *) paulson@13586: paulson@13586: header {* paulson@13586: \title{Pi and Function Sets} paulson@13586: \author{Florian Kammueller and Lawrence C Paulson} paulson@13586: *} paulson@13586: paulson@13586: theory FuncSet = Main: paulson@13586: paulson@13586: constdefs paulson@13586: Pi :: "['a set, 'a => 'b set] => ('a => 'b) set" paulson@13586: "Pi A B == {f. \x. x \ A --> f(x) \ B(x)}" paulson@13586: paulson@13586: extensional :: "'a set => ('a => 'b) set" paulson@13586: "extensional A == {f. \x. x~:A --> f(x) = arbitrary}" paulson@13586: paulson@13586: restrict :: "['a => 'b, 'a set] => ('a => 'b)" paulson@13586: "restrict f A == (%x. if x \ A then f x else arbitrary)" paulson@13586: paulson@13586: syntax paulson@13586: "@Pi" :: "[pttrn, 'a set, 'b set] => ('a => 'b) set" ("(3PI _:_./ _)" 10) paulson@13586: funcset :: "['a set, 'b set] => ('a => 'b) set" (infixr "->" 60) paulson@13586: "@lam" :: "[pttrn, 'a set, 'a => 'b] => ('a=>'b)" ("(3%_:_./ _)" [0,0,3] 3) paulson@13586: paulson@13586: syntax (xsymbols) paulson@13586: "@Pi" :: "[pttrn, 'a set, 'b set] => ('a => 'b) set" ("(3\ _\_./ _)" 10) paulson@13586: funcset :: "['a set, 'b set] => ('a => 'b) set" (infixr "\" 60) paulson@13586: "@lam" :: "[pttrn, 'a set, 'a => 'b] => ('a=>'b)" ("(3\_\_./ _)" [0,0,3] 3) paulson@13586: paulson@13586: translations paulson@13586: "PI x:A. B" => "Pi A (%x. B)" paulson@13586: "A -> B" => "Pi A (_K B)" paulson@13586: "%x:A. f" == "restrict (%x. f) A" paulson@13586: paulson@13586: constdefs paulson@13586: compose :: "['a set, 'b => 'c, 'a => 'b] => ('a => 'c)" paulson@13586: "compose A g f == \x\A. g (f x)" paulson@13586: paulson@13586: paulson@13586: paulson@13586: subsection{*Basic Properties of @{term Pi}*} paulson@13586: paulson@13586: lemma Pi_I: "(!!x. x \ A ==> f x \ B x) ==> f \ Pi A B" paulson@13586: by (simp add: Pi_def) paulson@13586: paulson@13586: lemma funcsetI: "(!!x. x \ A ==> f x \ B) ==> f \ A -> B" paulson@13586: by (simp add: Pi_def) paulson@13586: paulson@13586: lemma Pi_mem: "[|f: Pi A B; x \ A|] ==> f x \ B x" paulson@13593: by (simp add: Pi_def) paulson@13586: paulson@13586: lemma funcset_mem: "[|f \ A -> B; x \ A|] ==> f x \ B" paulson@13586: by (simp add: Pi_def) paulson@13586: paulson@13586: lemma Pi_eq_empty: "((PI x: A. B x) = {}) = (\x\A. B(x) = {})" paulson@13593: apply (simp add: Pi_def, auto) paulson@13586: txt{*Converse direction requires Axiom of Choice to exhibit a function paulson@13586: picking an element from each non-empty @{term "B x"}*} paulson@13593: apply (drule_tac x = "%u. SOME y. y \ B u" in spec, auto) paulson@13593: apply (cut_tac P= "%y. y \ B x" in some_eq_ex, auto) paulson@13586: done paulson@13586: paulson@13593: lemma Pi_empty [simp]: "Pi {} B = UNIV" paulson@13593: by (simp add: Pi_def) paulson@13593: paulson@13593: lemma Pi_UNIV [simp]: "A -> UNIV = UNIV" paulson@13593: by (simp add: Pi_def) paulson@13586: paulson@13586: text{*Covariance of Pi-sets in their second argument*} paulson@13586: lemma Pi_mono: "(!!x. x \ A ==> B x <= C x) ==> Pi A B <= Pi A C" paulson@13586: by (simp add: Pi_def, blast) paulson@13586: paulson@13586: text{*Contravariance of Pi-sets in their first argument*} paulson@13586: lemma Pi_anti_mono: "A' <= A ==> Pi A B <= Pi A' B" paulson@13586: by (simp add: Pi_def, blast) paulson@13586: paulson@13586: paulson@13586: subsection{*Composition With a Restricted Domain: @{term compose}*} paulson@13586: paulson@13586: lemma funcset_compose: paulson@13586: "[| f \ A -> B; g \ B -> C |]==> compose A g f \ A -> C" paulson@13586: by (simp add: Pi_def compose_def restrict_def) paulson@13586: paulson@13586: lemma compose_assoc: paulson@13586: "[| f \ A -> B; g \ B -> C; h \ C -> D |] paulson@13586: ==> compose A h (compose A g f) = compose A (compose B h g) f" paulson@13586: by (simp add: expand_fun_eq Pi_def compose_def restrict_def) paulson@13586: paulson@13586: lemma compose_eq: "x \ A ==> compose A g f x = g(f(x))" paulson@13593: by (simp add: compose_def restrict_def) paulson@13586: paulson@13586: lemma surj_compose: "[| f ` A = B; g ` B = C |] ==> compose A g f ` A = C" paulson@13593: by (auto simp add: image_def compose_eq) paulson@13586: paulson@13586: lemma inj_on_compose: paulson@13586: "[| f ` A = B; inj_on f A; inj_on g B |] ==> inj_on (compose A g f) A" paulson@13586: by (auto simp add: inj_on_def compose_eq) paulson@13586: paulson@13586: paulson@13586: subsection{*Bounded Abstraction: @{term restrict}*} paulson@13586: paulson@13586: lemma restrict_in_funcset: "(!!x. x \ A ==> f x \ B) ==> (\x\A. f x) \ A -> B" paulson@13586: by (simp add: Pi_def restrict_def) paulson@13586: paulson@13586: paulson@13586: lemma restrictI: "(!!x. x \ A ==> f x \ B x) ==> (\x\A. f x) \ Pi A B" paulson@13586: by (simp add: Pi_def restrict_def) paulson@13586: paulson@13586: lemma restrict_apply [simp]: paulson@13586: "(\y\A. f y) x = (if x \ A then f x else arbitrary)" paulson@13586: by (simp add: restrict_def) paulson@13586: paulson@13586: lemma restrict_ext: paulson@13586: "(!!x. x \ A ==> f x = g x) ==> (\x\A. f x) = (\x\A. g x)" paulson@13586: by (simp add: expand_fun_eq Pi_def Pi_def restrict_def) paulson@13586: paulson@13586: lemma inj_on_restrict_eq: "inj_on (restrict f A) A = inj_on f A" paulson@13593: by (simp add: inj_on_def restrict_def) paulson@13586: paulson@13586: paulson@13586: lemma Id_compose: paulson@13586: "[|f \ A -> B; f \ extensional A|] ==> compose A (\y\B. y) f = f" paulson@13586: by (auto simp add: expand_fun_eq compose_def extensional_def Pi_def) paulson@13586: paulson@13586: lemma compose_Id: paulson@13586: "[|g \ A -> B; g \ extensional A|] ==> compose A g (\x\A. x) = g" paulson@13586: by (auto simp add: expand_fun_eq compose_def extensional_def Pi_def) paulson@13586: paulson@13586: paulson@13586: subsection{*Extensionality*} paulson@13586: paulson@13586: lemma extensional_arb: "[|f \ extensional A; x\ A|] ==> f x = arbitrary" paulson@13593: by (simp add: extensional_def) paulson@13586: paulson@13586: lemma restrict_extensional [simp]: "restrict f A \ extensional A" paulson@13586: by (simp add: restrict_def extensional_def) paulson@13586: paulson@13586: lemma compose_extensional [simp]: "compose A f g \ extensional A" paulson@13586: by (simp add: compose_def) paulson@13586: paulson@13586: lemma extensionalityI: paulson@13586: "[| f \ extensional A; g \ extensional A; paulson@13586: !!x. x\A ==> f x = g x |] ==> f = g" paulson@13586: by (force simp add: expand_fun_eq extensional_def) paulson@13586: paulson@13586: lemma Inv_funcset: "f ` A = B ==> (\x\B. Inv A f x) : B -> A" paulson@13586: apply (unfold Inv_def) paulson@13586: apply (fast intro: restrict_in_funcset someI2) paulson@13586: done paulson@13586: paulson@13586: lemma compose_Inv_id: paulson@13586: "[| inj_on f A; f ` A = B |] paulson@13586: ==> compose A (\y\B. Inv A f y) f = (\x\A. x)" paulson@13586: apply (simp add: compose_def) paulson@13593: apply (rule restrict_ext, auto) paulson@13586: apply (erule subst) paulson@13586: apply (simp add: Inv_f_f) paulson@13586: done paulson@13586: paulson@13586: lemma compose_id_Inv: paulson@13586: "f ` A = B ==> compose B f (\y\B. Inv A f y) = (\x\B. x)" paulson@13586: apply (simp add: compose_def) paulson@13586: apply (rule restrict_ext) paulson@13586: apply (simp add: f_Inv_f) paulson@13586: done paulson@13586: paulson@13586: end