1-- The category of sets below a universe2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Category.SetMorphism8import Examples910-- Sets(U) is the category of the subsets of a universe set U with all11-- functions between them. A morphism f : A ⟶ B is the function graph of f12-- together with the entry (U ↦ B), which records the codomain: U is not a13-- member of any subset of U, so the entry leaves the values on A untouched,14-- and the codomain is read back as the value at U. A morphism therefore15-- applies to its arguments as an ordinary function, f(x), and composition16-- is composition of functions.17def setArrow (U B f : Set) : Set:= adjoinMap(f, U, B)1819-- The underlying function of a morphism: its graph without the codomain20-- entry.21def setsMap (U m : Set) : Set:= m ∖ {(U ↦ m(U))}2223theorem setArrow.membership (U B f p : Set)24shows p ∈ setArrow(U, B, f) ↔ (p = (U ↦ B) ∨ p ∈ f)25proof26simp [setArrow, adjoinMap, insert.membership]2728theorem universe.not_member (U A : Set)29requires subset : A ⊆ U30shows¬U ∈ A31proof32intro member33have inSelf := subset with U, member34have irreflexive := membership.irreflexive at U35exact irreflexive with inSelf3637theorem setArrow.function (U A B f : Set)38requires subset : A ⊆ U39requires function : f : A → B40shows setArrow(U, B, f) : insert(U, A) → insert(B, B)41proof42have notIn := universe.not_member with subset43unfold setArrow44exact adjoinMap.function with function, notIn4546theorem setArrow.apply (U A B f x : Set)47requires subset : A ⊆ U48requires function : f : A → B49requires xIn : x ∈ A50shows setArrow(U, B, f)(x) = f(x)51proof52have arrow := setArrow.function with subset, function53have xInserted : x ∈ insert(U, A) := insert.contains with xIn54have related := FunctionBetween.relates_apply with function, xIn55have lifted := adjoinMap.relates_old at f, U, B, x, f(x) with related56unfold setArrow at arrow57unfold setArrow58exact FunctionBetween.apply_value with arrow, xInserted, lifted5960theorem setArrow.codomain (U A B f : Set)61requires subset : A ⊆ U62requires function : f : A → B63shows setArrow(U, B, f)(U) = B64proof65have arrow := setArrow.function with subset, function66have uInserted : U ∈ insert(U, A) := insert.self at U, A67have related := adjoinMap.relates_new at f, U, B68unfold setArrow at arrow69unfold setArrow70exact FunctionBetween.apply_value with arrow, uInserted, related7172theorem setArrow.map (U A B f : Set)73requires subset : A ⊆ U74requires function : f : A → B75shows setsMap(U, setArrow(U, B, f)) = f76proof77have codomain := setArrow.codomain with subset, function78have notIn := universe.not_member with subset79unfold setsMap80rw codomain81ext p82constructor83 . intro member84obtain⟨inArrow, notEntry⟩:= difference.membership.forward with member85have shape := setArrow.membership.forward with inArrow86cases shape with entry | old87 . exfalso88have isEntry : p ∈ {(U ↦ B)} bysimp [entry]89exact notEntry with isEntry90 . exact old91 . intro member92apply difference.membership.backward93constructor94 . apply setArrow.membership.backward95right96exact member97 . intro isEntry98have entry : p = (U ↦ B) := singleton.membership.forward with isEntry99obtain⟨x, xInA, y, yInB, shape, related⟩:=100 FunctionBetween.member_shape with function, member101have same : (U, B) = (x, y) bycc102have uIsX : U = x := orderedPair.first with same103rw← uIsX at xInA104exact notIn with xInA105106-- A function with a two-sided inverse is a bijection.107theorem Bijective.of_two_sided_inverse (f g A B : Set)108requires function : f : A → B109requires inverse : g : B → A110requires leftLaw : ∀ x ∈ A, g(f(x)) = x111requires rightLaw : ∀ y ∈ B, f(g(y)) = y112shows BijectiveBetween(f, A, B)113proof114unfold BijectiveBetween115constructor116 . unfold InjectiveBetween117refine⟨function, ?_⟩118intros x hx y hy z hz relatesX relatesY119have valueX := FunctionBetween.apply_value with function, hx, relatesX120have valueY := FunctionBetween.apply_value with function, hy, relatesY121have leftX := leftLaw with x, hx122have leftY := leftLaw with y, hy123cc124 . unfold SurjectiveBetween125refine⟨function, ?_⟩126intros y hy127have preimage := FunctionBetween.apply_closed with inverse, hy128have edge := FunctionBetween.relates_apply with function, preimage129have value := rightLaw with y, hy130refine⟨g(y), preimage, ?_⟩131 rwa value at edge132133-- The domain of a function graph is its domain of definition.134theorem FunctionBetween.domain (f A B : Set)135requires function : f : A → B136shows domain(f) = A137proof138ext x139constructor140 . intro member141obtain⟨bounded, y, pairIn⟩:= domain.membership.forward with member142have related : relates(f, x, y) := pairIn143obtain⟨xInA, yInB⟩:= FunctionBetween.bounds with function, related144exact xInA145 . intro xInA146obtain⟨y, yInB, related⟩:= FunctionBetween.exists_value with function, xInA147have pairIn : (x, y) ∈ f := related148have singletonIn : {x} ∈ (x, y) bysimp [orderedPair, singleton, pair.membership]149have inUnion : {x} ∈⋃ f := union.contains with pairIn, singletonIn150have selfIn : x ∈ {x} := singleton.self at x151have inBound : x ∈⋃⋃ f := union.contains with inUnion, selfIn152have inCoordinates : x ∈ coordinateBound(f)153unfold coordinateBound154exact inBound155apply domain.membership.backward156refine⟨inCoordinates, y, pairIn⟩157158theorem functionSpace.bounded (U A B f : Set)159requires aIn : A ∈𝒫(U)160requires bIn : B ∈𝒫(U)161requires fIn : f ∈ functionSpace(A, B)162shows f ∈𝒫(U × U)163proof164have function := functionSpace.mem_iff.forward with fIn165have graph : f ⊆ A × B := function.left166have aSubset := powerset.membership_iff.forward with aIn167have bSubset := powerset.membership_iff.forward with bIn168have products := product.monotone with aSubset, bSubset169have bounded := Subset.transitive with graph, products170exact powerset.membership_iff.backward with bounded171172def setsBound (U : Set) : Set:= (U × U) ∪ ({U} ×𝒫(U))173174def setsMorphisms (U : Set) : Set:=175 { m ∈𝒫(setsBound(U)) |∃ A ∈𝒫(U), ∃ B ∈𝒫(U),176∃ f ∈ functionSpace(A, B), m = setArrow(U, B, f) }177178theorem setArrow.bounded (U A B f : Set)179requires aIn : A ∈𝒫(U)180requires bIn : B ∈𝒫(U)181requires fIn : f ∈ functionSpace(A, B)182shows setArrow(U, B, f) ∈𝒫(setsBound(U))183proof184have fBounded := functionSpace.bounded with aIn, bIn, fIn185have fSubset := powerset.membership_iff.forward with fBounded186have selfIn := singleton.self at U187have entryIn : (U, B) ∈ {U} ×𝒫(U) := product.pair with selfIn, bIn188apply powerset.membership_iff.backward189intros p member190have shape := setArrow.membership.forward with member191unfold setsBound192apply union2.membership.backward193cases shape with entry | old194 . right195rw entry196exact entryIn197 . left198exact fSubset with p, old199200theorem setsMorphisms.arrow (U A B f : Set)201requires aIn : A ∈𝒫(U)202requires bIn : B ∈𝒫(U)203requires fIn : f ∈ functionSpace(A, B)204shows setArrow(U, B, f) ∈ setsMorphisms(U)205proof206have bounded := setArrow.bounded with aIn, bIn, fIn207apply setsMorphisms.membership.backward208constructor209 . exact bounded210 . refine⟨A, aIn, B, bIn, f, fIn, rfl⟩211212theorem setsMorphisms.shape (U m : Set)213requires member : m ∈ setsMorphisms(U)214shows∃ A ∈𝒫(U), ∃ B ∈𝒫(U), ∃ f ∈ functionSpace(A, B), m = setArrow(U, B, f)215proof216obtain⟨bounded, rest⟩:= setsMorphisms.membership.forward with member217exact rest218219-- The codomain of a morphism is its value at U; its domain is the domain220-- of its underlying function.221defgraph setsCod (U : Set) (m ∈ setsMorphisms(U)) : 𝒫(U) := m(U)222proof223obtain⟨A, aIn, B, bIn, f, fIn, shape⟩:= setsMorphisms.shape with member224have subset := powerset.membership_iff.forward with aIn225have function := functionSpace.mem_iff.forward with fIn226have value := setArrow.codomain with subset, function227rw shape228rw value229exact bIn230231defgraph setsDom (U : Set) (m ∈ setsMorphisms(U)) : 𝒫(U) := domain(setsMap(U, m))232proof233obtain⟨A, aIn, B, bIn, f, fIn, shape⟩:= setsMorphisms.shape with member234have subset := powerset.membership_iff.forward with aIn235have function := functionSpace.mem_iff.forward with fIn236have underlying := setArrow.map with subset, function237have domainValue := FunctionBetween.domain with function238rw shape239rw [underlying, domainValue]240exact aIn241242theorem setsCod.arrow (U A B f : Set)243requires aIn : A ∈𝒫(U)244requires bIn : B ∈𝒫(U)245requires fIn : f ∈ functionSpace(A, B)246shows setsCod(U)(setArrow(U, B, f)) = B247proof248have member := setsMorphisms.arrow with aIn, bIn, fIn249have subset := powerset.membership_iff.forward with aIn250have function := functionSpace.mem_iff.forward with fIn251have value := setsCod.value with member252have codomain := setArrow.codomain with subset, function253rw value254exact codomain255256theorem setsDom.arrow (U A B f : Set)257requires aIn : A ∈𝒫(U)258requires bIn : B ∈𝒫(U)259requires fIn : f ∈ functionSpace(A, B)260shows setsDom(U)(setArrow(U, B, f)) = A261proof262have member := setsMorphisms.arrow with aIn, bIn, fIn263have subset := powerset.membership_iff.forward with aIn264have function := functionSpace.mem_iff.forward with fIn265have value := setsDom.value with member266have underlying := setArrow.map with subset, function267have domainValue := FunctionBetween.domain with function268rw value269rw underlying270exact domainValue271272theorem setsMap.arrow (U A B f : Set)273requires aIn : A ∈𝒫(U)274requires fIn : f ∈ functionSpace(A, B)275shows setsMap(U, setArrow(U, B, f)) = f276proof277have subset := powerset.membership_iff.forward with aIn278have function := functionSpace.mem_iff.forward with fIn279exact setArrow.map with subset, function280281-- Identities and composition.282defgraph setsIdentity (U : Set) (A ∈𝒫(U)) : setsMorphisms(U) :=283 setArrow(U, A, identity(A))284proof285have identityIn := functionSpace.identity at A286exact setsMorphisms.arrow with member, member, identityIn287288defgraph setsComposition (U : Set)289 (p ∈ composablePairsOf(setsMorphisms(U), setsDom(U), setsCod(U))) :290 setsMorphisms(U) :=291 setArrow(U, setsCod(U)(fst(p)),292 compose(setsMap(U, fst(p)), setsMap(U, snd(p)), setsDom(U)(snd(p)),293 setsCod(U)(snd(p)), setsCod(U)(fst(p))))294proof295obtain⟨bounded, g, gIn, f, fIn, shape, composable⟩:=296 composablePairsOf.membership.forward with member297obtain⟨B, bIn, C, cIn, gMap, gMapIn, gShape⟩:= setsMorphisms.shape with gIn298obtain⟨A, aIn, D, dIn, fMap, fMapIn, fShape⟩:= setsMorphisms.shape with fIn299have domG := setsDom.arrow with bIn, cIn, gMapIn300have codG := setsCod.arrow with bIn, cIn, gMapIn301have mapG := setsMap.arrow with bIn, gMapIn302have codF0 := setsCod.arrow with aIn, dIn, fMapIn303have middle : B = D bycc304rw← middle at fMapIn305rw← middle at fShape306have domF := setsDom.arrow with aIn, bIn, fMapIn307have codF := setsCod.arrow with aIn, bIn, fMapIn308have mapF := setsMap.arrow with aIn, fMapIn309have composed := functionSpace.compose with fMapIn, gMapIn310rw shape311rw [fst.pair, snd.pair, gShape, fShape, codG, codF, domF, mapG, mapF]312exact setsMorphisms.arrow with aIn, cIn, composed313314theorem setsComposition.arrow (U A B C f g : Set)315requires aIn : A ∈𝒫(U)316requires bIn : B ∈𝒫(U)317requires cIn : C ∈𝒫(U)318requires fIn : f ∈ functionSpace(A, B)319requires gIn : g ∈ functionSpace(B, C)320shows setsComposition(U)(setArrow(U, C, g), setArrow(U, B, f)) =321 setArrow(U, C, compose(g, f, A, B, C))322proof323have gMember := setsMorphisms.arrow with bIn, cIn, gIn324have fMember := setsMorphisms.arrow with aIn, bIn, fIn325have domG := setsDom.arrow with bIn, cIn, gIn326have codF := setsCod.arrow with aIn, bIn, fIn327have domF := setsDom.arrow with aIn, bIn, fIn328have codG := setsCod.arrow with bIn, cIn, gIn329have mapG := setsMap.arrow with bIn, gIn330have mapF := setsMap.arrow with aIn, fIn331have composable : setsDom(U)(setArrow(U, C, g)) = setsCod(U)(setArrow(U, B, f))332cc333have pairIn := composablePairsOf.pair at setsMorphisms(U), setsDom(U),334 setsCod(U), setArrow(U, C, g), setArrow(U, B, f) with335 gMember, fMember, composable336have value := setsComposition.value with pairIn337have firstValue := fst.pair at setArrow(U, C, g), setArrow(U, B, f)338have secondValue := snd.pair at setArrow(U, C, g), setArrow(U, B, f)339simp [call2]340341def Sets (U : Set) : Set:=342 Category.mk(𝒫(U), setsMorphisms(U), setsDom(U), setsCod(U), setsIdentity(U),343 setsComposition(U))344345theorem Sets.obj (U : Set)346shows obj(Sets(U)) =𝒫(U)347proof348simp [Sets, Category.mk.obj]349350theorem Sets.mor (U : Set)351shows mor(Sets(U)) = setsMorphisms(U)352proof353simp [Sets, Category.mk.mor]354355theorem Sets.dom (U : Set)356shows dom(Sets(U)) = setsDom(U)357proof358simp [Sets, Category.mk.dom]359360theorem Sets.cod (U : Set)361shows cod(Sets(U)) = setsCod(U)362proof363simp [Sets, Category.mk.cod]364365theorem Sets.comp (U : Set)366shows comp(Sets(U)) = setsComposition(U)367proof368simp [Sets, Category.mk.comp]369370theorem Sets.id (U : Set)371shows id(Sets(U)) = setsIdentity(U)372proof373simp [Sets, Category.mk.id]374375tactic sets_projections :=simp [Sets.obj, Sets.mor, Sets.dom, Sets.cod, Sets.comp, Sets.id]376377theorem Sets.category (U : Set)378shows Category(Sets(U))379proof380have domFunction := setsDom.function at U381have codFunction := setsCod.function at U382have idFunction := setsIdentity.function at U383have compFunction := setsComposition.function at U384unfold Sets385apply Category.intro with domFunction, codFunction, idFunction, compFunction386 . intros A aIn387have idValue := setsIdentity.value with aIn388have identityIn := functionSpace.identity at A389have domValue := setsDom.arrow with aIn, aIn, identityIn390have codValue := setsCod.arrow with aIn, aIn, identityIn391rw idValue392refine⟨domValue, codValue⟩393 . intros g gIn f fIn composable394obtain⟨B, bIn, C, cIn, gMap, gMapIn, gShape⟩:= setsMorphisms.shape with gIn395obtain⟨A, aIn, D, dIn, fMap, fMapIn, fShape⟩:= setsMorphisms.shape with fIn396have domG := setsDom.arrow with bIn, cIn, gMapIn397have codF := setsCod.arrow with aIn, dIn, fMapIn398have middle : B = D bycc399rw← middle at fMapIn400rw← middle at fShape401have composite := setsComposition.arrow with aIn, bIn, cIn, fMapIn, gMapIn402have composed := functionSpace.compose with fMapIn, gMapIn403have domComposite := setsDom.arrow with aIn, cIn, composed404have codComposite := setsCod.arrow with aIn, cIn, composed405have domF := setsDom.arrow with aIn, bIn, fMapIn406have codG := setsCod.arrow with bIn, cIn, gMapIn407rw [gShape, fShape, composite]408refine⟨?_, ?_⟩409 . cc410 . cc411 . intros f fIn412obtain⟨A, aIn, B, bIn, fMap, fMapIn, fShape⟩:= setsMorphisms.shape with fIn413have domF := setsDom.arrow with aIn, bIn, fMapIn414have codF := setsCod.arrow with aIn, bIn, fMapIn415have aIdentity := setsIdentity.value with aIn416have bIdentity := setsIdentity.value with bIn417have aIdentityIn := functionSpace.identity at A418have bIdentityIn := functionSpace.identity at B419have leftComposite := setsComposition.arrow with420 aIn, bIn, bIn, fMapIn, bIdentityIn421have rightComposite := setsComposition.arrow with422 aIn, aIn, bIn, aIdentityIn, fMapIn423have function := functionSpace.mem_iff.forward with fMapIn424have leftUnit := compose.identity_left with function425have rightUnit := compose.identity_right with function426rw fShape427rw [domF, codF, aIdentity, bIdentity, leftComposite, rightComposite]428rw [leftUnit, rightUnit]429refine⟨rfl, rfl⟩430 . intros h hIn g gIn f fIn outer inner431obtain⟨C, cIn, D, dIn, hMap, hMapIn, hShape⟩:= setsMorphisms.shape with hIn432obtain⟨B, bIn, E, eIn, gMap, gMapIn, gShape⟩:= setsMorphisms.shape with gIn433obtain⟨A, aIn, K, kIn, fMap, fMapIn, fShape⟩:= setsMorphisms.shape with fIn434have domH := setsDom.arrow with cIn, dIn, hMapIn435have codG := setsCod.arrow with bIn, eIn, gMapIn436have domG := setsDom.arrow with bIn, eIn, gMapIn437have codF := setsCod.arrow with aIn, kIn, fMapIn438have outerMiddle : C = E bycc439have innerMiddle : B = K bycc440rw← outerMiddle at gMapIn441rw← outerMiddle at gShape442rw← innerMiddle at fMapIn443rw← innerMiddle at fShape444have hg := setsComposition.arrow with bIn, cIn, dIn, gMapIn, hMapIn445have gf := setsComposition.arrow with aIn, bIn, cIn, fMapIn, gMapIn446have hgIn := functionSpace.compose with gMapIn, hMapIn447have gfIn := functionSpace.compose with fMapIn, gMapIn448have leftComposite := setsComposition.arrow with aIn, bIn, dIn, fMapIn, hgIn449have rightComposite := setsComposition.arrow with450 aIn, cIn, dIn, gfIn, hMapIn451have fFunction := functionSpace.mem_iff.forward with fMapIn452have gFunction := functionSpace.mem_iff.forward with gMapIn453have hFunction := functionSpace.mem_iff.forward with hMapIn454have associative := compose.associative with fFunction, gFunction, hFunction455rw [hShape, gShape, fShape, hg, gf, leftComposite, rightComposite]456rw associative457rfl458459-- Morphisms of Sets(U) as functions: a hom-set is the function space, up460-- to the codomain entry, and a morphism applies as a function.461section SetsLaws462variable (U : Set)463hypothesis sets : Category(Sets(U))464465theorem Sets.hom_shape (A B m : Set)466requires mHom : m ∈ hom(Sets(U), A, B)467shows∃ f ∈ functionSpace(A, B), m = setArrow(U, B, f)468proof469obtain⟨mIn, domM, codM⟩:= hom.membership.forward with mHom470simp [Sets.obj, Sets.mor, Sets.dom, Sets.cod, Sets.comp, Sets.id] at mIn471simp [Sets.obj, Sets.mor, Sets.dom, Sets.cod, Sets.comp, Sets.id] at domM472simp [Sets.obj, Sets.mor, Sets.dom, Sets.cod, Sets.comp, Sets.id] at codM473obtain⟨A2, aIn, B2, bIn, f, fIn, shape⟩:= setsMorphisms.shape with mIn474have domValue := setsDom.arrow with aIn, bIn, fIn475have codValue := setsCod.arrow with aIn, bIn, fIn476have sameA : A2 = A bycc477have sameB : B2 = B bycc478rw [sameA, sameB] at fIn479rw sameB at shape480refine⟨f, fIn, shape⟩481482theorem Sets.arrow_hom (A B f : Set)483requires aIn : A ∈𝒫(U)484requires bIn : B ∈𝒫(U)485requires function : f : A → B486shows setArrow(U, B, f) : A ⟶ B487proof488have fIn := functionSpace.mem_iff.backward with function489have member := setsMorphisms.arrow with aIn, bIn, fIn490have domValue := setsDom.arrow with aIn, bIn, fIn491have codValue := setsCod.arrow with aIn, bIn, fIn492unfold Morphism493rw [Sets.mor, Sets.dom, Sets.cod]494refine⟨member, domValue, codValue⟩495496theorem Sets.object (A B : Set) (f : A ⟶ B)497shows A ∈𝒫(U)498proof499have aIn : A ∈ obj(Sets(U)) := Morphism.dom_object with*500simp [Sets.obj, Sets.mor, Sets.dom, Sets.cod, Sets.comp, Sets.id] at aIn501exact aIn502503theorem Sets.target (A B : Set) (f : A ⟶ B)504shows B ∈𝒫(U)505proof506have bIn : B ∈ obj(Sets(U)) := Morphism.cod_object with*507simp [Sets.obj, Sets.mor, Sets.dom, Sets.cod, Sets.comp, Sets.id] at bIn508exact bIn509510theorem Sets.function (A B : Set) (f : A ⟶ B)511shows setsMap(U, f) : A → B512proof513have fHom : f ∈ hom(Sets(U), A, B) := Morphism.hom with*514have aIn := Sets.object with*515obtain⟨f0, f0In, shape⟩:= Sets.hom_shape with sets, fHom516have function := functionSpace.mem_iff.forward with f0In517have underlying := setsMap.arrow with aIn, f0In518rw shape519rw underlying520exact function521522theorem Sets.arrow_apply (A B f x : Set)523requires aIn : A ∈𝒫(U)524requires function : f : A → B525requires xIn : x ∈ A526shows setArrow(U, B, f)(x) = f(x)527proof528have subset := powerset.membership_iff.forward with aIn529exact setArrow.apply with subset, function, xIn530531theorem Sets.apply_map (A B : Set) (f : A ⟶ B) (x : Set)532requires xIn : x ∈ A533shows f(x) = setsMap(U, f)(x)534proof535have fHom : f ∈ hom(Sets(U), A, B) := Morphism.hom with*536have aIn := Sets.object with*537obtain⟨f0, f0In, shape⟩:= Sets.hom_shape with sets, fHom538have function := functionSpace.mem_iff.forward with f0In539have underlying := setsMap.arrow with aIn, f0In540have value := Sets.arrow_apply with sets, aIn, function, xIn541rw shape542rw [underlying, value]543rfl544545theorem Sets.apply_closed (A B : Set) (f : A ⟶ B) (x : Set)546requires xIn : x ∈ A547shows f(x) ∈ B548proof549have function := Sets.function with*550have value := Sets.apply_map with*551rw value552exact FunctionBetween.apply_closed with function, xIn553554theorem Sets.id_apply (A x : Set)555requires aIn : A ∈𝒫(U)556requires xIn : x ∈ A557shows id(Sets(U))(A)(x) = x558proof559have idValue := setsIdentity.value with aIn560have identityFunction := identity.function at A561have applied := identity.apply with xIn562have arrowValue := Sets.arrow_apply with sets, aIn, identityFunction, xIn563rw [Sets.id, idValue, arrowValue]564exact applied565566theorem Sets.comp_apply (A B C : Set) (f : A ⟶ B) (g : B ⟶ C) (x : Set)567requires xIn : x ∈ A568shows (g ∘ f)(x) = g(f(x))569proof570have fHom : f ∈ hom(Sets(U), A, B) := Morphism.hom with*571have gHom : g ∈ hom(Sets(U), B, C) := Morphism.hom with*572have fTyped := Morphism.of_hom with fHom573have gTyped := Morphism.of_hom with gHom574have aIn : A ∈ obj(Sets(U)) := Morphism.dom_object with sets, fTyped575have bIn : B ∈ obj(Sets(U)) := Morphism.cod_object with sets, fTyped576have cIn : C ∈ obj(Sets(U)) := Morphism.cod_object with sets, gTyped577rw Sets.obj at aIn578rw Sets.obj at bIn579rw Sets.obj at cIn580obtain⟨f0, f0In, fShape⟩:= Sets.hom_shape with sets, fHom581obtain⟨g0, g0In, gShape⟩:= Sets.hom_shape with sets, gHom582have fFunction := functionSpace.mem_iff.forward with f0In583have gFunction := functionSpace.mem_iff.forward with g0In584have composite := setsComposition.arrow with aIn, bIn, cIn, f0In, g0In585have composed := compose.function with fFunction, gFunction586have composedValue := compose.apply with fFunction, gFunction, xIn587have fValue := Sets.arrow_apply with sets, aIn, fFunction, xIn588have fxIn := FunctionBetween.apply_closed with fFunction, xIn589have gValue := Sets.arrow_apply with sets, bIn, gFunction, fxIn590have compositeValue := Sets.arrow_apply with sets, aIn, composed, xIn591have operation := Sets.comp at U592rw [fShape, gShape]593rw [operation, composite, compositeValue, fValue, gValue]594exact composedValue595596theorem Sets.ext (A B : Set) (f g : A ⟶ B)597requires same : ∀ x ∈ A, f(x) = g(x)598shows f = g599proof600have fHom : f ∈ hom(Sets(U), A, B) := Morphism.hom with*601have gHom : g ∈ hom(Sets(U), A, B) := Morphism.hom with*602have fTyped := Morphism.of_hom with fHom603have aIn : A ∈ obj(Sets(U)) := Morphism.dom_object with sets, fTyped604rw Sets.obj at aIn605obtain⟨f0, f0In, fShape⟩:= Sets.hom_shape with sets, fHom606obtain⟨g0, g0In, gShape⟩:= Sets.hom_shape with sets, gHom607have fFunction := functionSpace.mem_iff.forward with f0In608have gFunction := functionSpace.mem_iff.forward with g0In609have agree : ∀ x ∈ A, f0(x) = g0(x)610intros x xIn611have fValue := Sets.arrow_apply with sets, aIn, fFunction, xIn612have gValue := Sets.arrow_apply with sets, aIn, gFunction, xIn613have equal := same with x, xIn614rw [fShape, gShape] at equal615rw [fValue, gValue] at equal616exact equal617have underlying := FunctionBetween.ext with fFunction, gFunction, agree618rw [fShape, gShape, underlying]619rfl620621end SetsLaws622623-- The rewrite set for values of morphisms of Sets(U): composites and624-- identities apply pointwise, and an arrow built from a function applies625-- as that function.626tactic sets_simp :=simp [Sets.comp_apply, Sets.id_apply, Sets.arrow_apply]627