\import Function.Meta ($)
\import Logic
\import Logic.Meta
\import Meta
\import Order.Directed
\import Order.Lattice
\import Order.PartialOrder
\import Paths
\import Paths.Meta
\import Set
\import Set.Category
\import Set.Filter
\import Set.Subset
\open Bounded(top)
\class TopSpace \extends BaseSet {
| isOpen : Set E -> \Prop
| open-top : isOpen Bounded.top
| open-inter {U V : Set E} : isOpen U -> isOpen V -> isOpen (U ∧ V)
| open-Union {S : Set (Set E)} : ∀ {U : S} (isOpen U) -> isOpen (Set.Union S)
\lemma cover-open {U : Set E} (c : ∀ {x : U} ∃ (V : isOpen) (V x) (V ⊆ U)) : isOpen U
=> \have uo => open-Union {_} {\lam V => \Sigma (isOpen V) (V ⊆ U)} __.1
\in transport isOpen (ext \lam x => ext (\lam (inP (V,(_,V<=U),Vx)) => V<=U Vx, \lam Ux => TruncP.map (c Ux) \lam (V,Vo,Vx,V<=U) => (V, (Vo, V<=U), Vx))) uo
\lemma open-IUnion {J : \hType} (g : J -> Given isOpen) : isOpen \lam x => ∃ (j : J) ((g j).1 x)
=> \have uo => open-Union {_} {\lam U => ∃ (j : J) ((g j).1 = U)} \lam (inP (j,p)) => transport isOpen p (g j).2
\in transport isOpen (ext \lam x => ext (\lam (inP (U, inP (j,p), Ux)) => inP (j, rewrite p Ux), \lam (inP (j,c)) => inP ((g j).1, inP (j, idp), c))) uo
\type \infix 4 <=<T (V U : Set E) : \Prop
=> \Pi (y : E) -> ∃ (W : isOpen) (W y) (Given (V ∧ W) -> W ⊆ U)
\func IsRegular => ∀ {U : isOpen} {x : U} ∃ (V : isOpen) (V x) (V <=<T U)
\func IsLimit {I : DirectedSet} (f : I -> E) (l : E) : \Prop
=> ∀ {U : isOpen} (U l) ∃ (N : I) ∀ {n} (N <= n -> U (f n))
\func IsClosed (U : Set E) : \Prop
=> \Pi {x : E} -> (\Pi {V : Set E} -> isOpen V -> V x -> ∃ (U ∧ V)) -> U x
}
\func NFilter {X : TopSpace} (x : X) : ProperFilter X \cowith
| F U => ∃ (V : isOpen) (V x) (V ⊆ U)
| filter-mono p (inP (W,Wo,Wx,q)) => inP (W, Wo, Wx, q <=∘ p)
| filter-top => inP (top, open-top, (), <=-refl)
| filter-meet (inP (U,Uo,Ux,p)) (inP (V,Vo,Vx,q)) => inP (U ∧ V, open-inter Uo Vo, (Ux,Vx), MeetSemilattice.meet-monotone p q)
| isProper (inP (V,Vo,Vx,p)) => inP (x, p Vx)
\func IsDenseSet {X : TopSpace} (S : Set X) : \Prop
=> \Pi {x : X} {U : Set X} -> isOpen U -> U x -> ∃ (y : S) (U y)
\record ContMap \extends SetHom {
\override Dom : TopSpace
\override Cod : TopSpace
| func-cont {U : Cod -> \Prop} : isOpen U -> isOpen \lam x => U (func x)
\func IsDense : \Prop
=> IsDenseSet (\lam y => ∃ (x : Dom) (func x = y))
\func IsEmbedding : \Prop
=> ∀ {U : isOpen} ∃ (V : isOpen) (U = func ^-1 V)
\lemma embedding-char : IsEmbedding <-> ∀ {U : isOpen} {x : U} ∃ (V : isOpen) (V (func x)) (func ^-1 V ⊆ U)
=> (\lam e Uo Ux => \case e Uo \with {
| inP (V,Vo,p) => inP (V, Vo, rewrite p in Ux, rewrite p <=-refl)
}, \lam e {U} Uo => inP (_, open-Union {_} {\lam V => \Sigma (isOpen V) (func ^-1 V ⊆ U)} __.1, ext \lam x => ext (\lam Ux => \case e Uo Ux \with {
| inP (V,Vo,Vfx,p) => inP (V, (Vo, p), Vfx)
}, \lam (inP (V,(Vo,p),Vfx)) => p Vfx)))
\func IsDenseEmbedding : \Prop
=> \Sigma IsDense IsEmbedding
} \where {
\func id {X : TopSpace} : ContMap X X \cowith
| func x => x
| func-cont Uo => Uo
\func compose \alias \infixl 8 ∘ {X Y Z : TopSpace} (g : ContMap Y Z) (f : ContMap X Y) : ContMap X Z \cowith
| func x => g (f x)
| func-cont Uo => f.func-cont (g.func-cont Uo)
\func const {Y X : TopSpace} (x : X) : ContMap Y X \cowith
| func _ => x
| func-cont _ => Y.cover-open \lam Ux => inP (top, open-top, (), \lam _ => Ux)
}
\lemma const-limit {I : DirectedSet} {X : TopSpace} {x : X} : X.IsLimit (\lam (_ : I) => x) x
=> \lam _ Ux => \case I.isInhabitted \with {
| inP N => inP (N, \lam _ => Ux)
}
\lemma cont-limit {I : DirectedSet} {X Y : TopSpace} {f : I -> X} {l : X} (p : X.IsLimit f l) (g : ContMap X Y) : Y.IsLimit (\lam n => g (f n)) (g l)
=> \lam Uo Ugl => p (g.func-cont Uo) Ugl
\class HausdorffTopSpace \extends TopSpace
| isHausdorff {x y : E} : ∀ {U V : isOpen} (U x) (V y) ∃ (U ∧ V) -> x = y
\lemma denseSet-lift-unique {X : TopSpace} {Y : HausdorffTopSpace} {S : Set X} (Sd : IsDenseSet S) (f g : ContMap X Y) (p : \Pi {x : X} -> S x -> f x = g x) (x : X) : f x = g x
=> isHausdorff \lam {U} Uo Vo Ufx Vgx => \case Sd {x} (open-inter (f.func-cont Uo) (g.func-cont Vo)) (Ufx,Vgx) \with {
| inP (y,Sy,(Ufy,Vgy)) => inP (g y, (transport U (p Sy) Ufy, Vgy))
}
\lemma dense-lift-unique {X Y : TopSpace} {Z : HausdorffTopSpace} (f : ContMap X Y) (fd : f.IsDense) (g h : ContMap Y Z) (p : \Pi (x : X) -> g (f x) = h (f x)) (y : Y) : g y = h y
=> denseSet-lift-unique fd g h (\lam (inP (x,q)) => rewriteI q (p x)) y
\func TopTransfer {X : \Set} {Y : TopSpace} (f : X -> Y) : TopSpace X \cowith
| isOpen U => ∃ (V : isOpen) (U = f ^-1 V)
| open-top => inP (top, open-top, idp)
| open-inter (inP (V,Vo,p)) (inP (V',V'o,p')) => inP (V ∧ V', open-inter Vo V'o, pmap2 (∧) p p')
| open-Union {S} h => inP (Set.Union \lam V => \Sigma (isOpen V) (f ^-1 V ⊆ Set.Union S), open-Union __.1, <=-antisymmetric (\lam (inP (U,SU,Ux)) => \case h SU \with {
| inP (V,Vo,p) => inP (V, (Vo, rewriteI p $ Set.Union-cond SU), rewrite p in Ux)
}) (\lam (inP (V,(Vo,p),Vfx)) => p Vfx))