\import Algebra.Meta
\import Category
\import Category.CartesianClosed
\import Category.Coreflection
\import Category.Limit
\import Equiv
\import Function (IsInj)
\import Function.Meta
\import Logic
\import Meta
\import Paths
\import Paths.Meta
\import Set.SetCategory
\open PrecatWithBprod
\class ToposPrecat \extends FinCompletePrecat, CartesianClosedPrecat {
| subobj-classifier \alias omega : Ob
| true-map : Hom terminal omega
| char-map {S B : Ob} (m : Mono {\this} {S} {B}) : Hom B omega
| char-pullback {S B : Ob} (m : Mono {\this} {S} {B}) : Pullback {\this} (char-map m) true-map S m terminalMap
| char-unique {S B : Ob} {m : Mono {\this} {S} {B}} {phi : Hom B omega}
(phi-pull : Pullback phi true-map S m terminalMap) : phi = char-map m
| p-exponential : isExponentiable omega
\default p-exponential => CartesianClosedPrecat.is-exponentiable omega
\use \func Power (B : Ob) : Ob
=> p-exponential B
\use \func belongs {B : Ob} : Hom (Bprod (Power B) B) omega
=> corefl-map {p-exponential B}
\use \func p-transpose {A B : Ob} (f : Hom (Bprod A B) omega) : Hom A (Power B)
=> ret {isCoreflection {p-exponential B}} f
\use \lemma p-transpose-univ {A B : Ob} (f : Hom (Bprod A B) omega) : f = belongs ∘ (prodMap (p-transpose f) (id B))
=> inv $ Equiv.f_ret {isCoreflection {p-exponential B}} f
\use \lemma p-transpose-unique {A B : Ob} {f : Hom (Bprod A B) omega} {g : Hom A (Power B)} (comm : f = belongs ∘ prodMap g (id B)) : g = p-transpose f
=> Equiv.adjoint {isCoreflection {p-exponential B}} (inv comm)
\use \func anti-transpose {A B : Ob} (g : Hom A (Power B)) : Hom (Bprod A B) omega
=> belongs ∘ (prodMap g (id B))
\use \lemma antitranspose-eq {A B : Ob} (f : Hom (Bprod B A) omega) : f = anti-transpose (p-transpose f)
=> p-transpose-univ f
\use \lemma transpose-inj {A B : Ob} {f g : Hom (Bprod A B) omega} (e : p-transpose f = p-transpose g) : f = g
=> p-transpose-univ f *> pmap (belongs ∘ prodMap __ (id B)) e *> (inv $ p-transpose-univ g)
\use \func internal-equality \alias eq (B : Ob) : Hom (Bprod B B) omega
=> char-map (diagonal.isSplitMono B)
\use \func singleton (B : Ob) : Hom B (Power B)
=> p-transpose (eq B)
\use \func char-rel {B C : Ob} (f : Hom B C) : Hom (Bprod B C) omega
=> eq C ∘ prodMap f (id C)
\use \lemma eqq-p-transpose-s {B X : Ob} (b : Hom X B) : singleton B ∘ b = p-transpose (char-rel b)
=> p-transpose-unique {\this} {_} {_} {char-rel b} $ rewrite (prod-id-right _ _, inv o-assoc, inv $ p-transpose-univ _) idp
\private \use \lemma pbBeta2' {B X : Ob} {b : Hom X B} (w : Ob) (p1 : Hom w (Bprod X B))
(p2 : Hom w B) (c : prodMap b (id B) ∘ p1 = diagonal B ∘ p2) : b ∘ (proj1 ∘ p1) = p2 =>
\let left : proj1 ∘ (diagonal B ∘ p2) = p2 => rewriteI o-assoc $ rewrite (beta1 _ _) equation
| right : proj1 ∘ (prodMap b (id B) ∘ p1) = b ∘ (proj1 ∘ p1) =>
rewriteI o-assoc $ rewrite (beta1 _ _) o-assoc
\in
inv right *> pmap (proj1 ∘ __) c *> left
\private \use \func left-square {B X : Ob} {b : Hom X B} : Pullback (prodMap b (id B)) (diagonal B) X (pair (id X) b) b \cowith
| pbCoh => pair-unique
(run {
rewriteI o-assoc,
rewrite (beta1 _ _, o-assoc, beta1 _ _, id-right),
rewriteI o-assoc,
rewrite (beta1 _ _, id-left),
idp
})
(run {
rewriteI o-assoc,
rewrite (beta2 _ _),
rewriteI o-assoc, rewrite (beta2 _ _, o-assoc, beta2 _ _) equation
})
| pbMap p1 _ _ => proj1 ∘ p1
| pbBeta1 {w} {p1} {p2} {c} =>
\let
left : proj2 ∘ (diagonal B ∘ p2) = p2 => rewriteI o-assoc $ rewrite (beta2 _ _) equation
| right : proj2 ∘ (prodMap b (id B) ∘ p1) = proj2 ∘ p1 => rewriteI o-assoc $ rewrite (beta2 _ _) equation \in
pair-unique
(run {
rewriteI o-assoc,
rewrite (beta1 _ _ ),
equation
})
(run {rewriteI o-assoc,
rewrite (beta2 _ _),
pbBeta2' w p1 p2 c *> inv left *> pmap (proj2 ∘ __) (inv c) *> right
})
| pbBeta2 {w} {p1} {p2} {c} => pbBeta2' w p1 p2 c
| pbEta {_} {h1} {h2} c _ =>
\let p2 : h1 = proj1 ∘ (pair (id X) b ∘ h1) => rewriteI o-assoc $ rewrite (beta1 _ _) equation
| p1 : proj1 ∘ (pair (id X) b ∘ h2) = h2 => rewriteI o-assoc $ rewrite (beta1 _ _) equation
\in p2 *> pmap (proj1 ∘ __) c *> p1
\private \use \func right-square {B : Ob} : Pullback {\this} {Bprod B B} {terminal} {omega} (eq B) true-map B (diagonal B) terminalMap
=> char-pullback (diagonal.isSplitMono B)
\private \use \func full-square {B X : Ob} (b : Hom X B) : Pullback {\this} (char-rel b) true-map X (pair (id X) b)
=> pullback-lemma right-square left-square
\use \lemma singleton-mono (B : Ob) : Mono (singleton B) \cowith
| isMono {X} {b} {b'} sb=sb' =>
\let
| c : char-rel b = char-rel b' => transpose-inj ((inv $ eqq-p-transpose-s b) *> sb=sb' *> eqq-p-transpose-s b')
| b-square => full-square b
| b'-square : Pullback {\this} (char-rel b) true-map X (pair (id X) b') =>
transport (Pullback {\this} __ true-map X (pair (id X) b')) (inv c) (full-square b')
| h-iso : Iso {\this} {X} {X} => Pullback.unique (char-rel b) true-map b-square b'-square
| pb~pb*h : pair (id X) b = pair (id X) b' ∘ h-iso => inv (Pullback.unique.p-beta1 b'-square b-square)
| c' : proj1 ∘ (pair (id X) b' ∘ h-iso.f) = h-iso.f => rewriteI o-assoc $ rewrite (beta1 _ _) id-left
| h~1 : id X = h-iso.f => inv (beta1 _ _) *> pmap (proj1 ∘ __) pb~pb*h *> c'
| b~b'h : b = b' ∘ h-iso.f => inv (beta2 _ _) *> pmap (proj2 ∘ __) pb~pb*h *> (rewriteI o-assoc $ rewrite (beta2 _ _) idp)
\in b~b'h *> rewriteI h~1 id-right
\use \func is-singleton {B : Ob} : Hom (Power B) omega => char-map (singleton-mono B)
\use \func true-over-obj {B : Ob} : Hom B omega => true-map ∘ terminalMap
\use \lemma monic-is-regular {X Y : Ob} (m : Mono {\this} {X} {Y}) : Equalizer true-over-obj (char-map m) X m \cowith
| equal =>
rewrite (pbCoh {char-pullback m}, o-assoc) $
rewrite terminal-unique idp
| isEqualizer _ => \new QEquiv {
| ret (h, com) => pbMap {char-pullback m} h terminalMap
(rewriteI com $ rewrite o-assoc $ rewrite terminal-unique idp)
| ret_f _ => pbEta {char-pullback m} (rewrite (pbBeta1 {char-pullback m}) $ idp)
(rewrite (pbBeta2 {char-pullback m}) terminal-unique)
| f_sec (h, com) => exts $ rewrite (pbBeta1 {char-pullback m}) idp
}
\use \lemma monic+epi=iso {X Y : Ob} (m : Mono {\this} {X} {Y}) (m-is-epi : isEpi {\this} {X} {Y} m)
: Iso {\this} {X} {Y} m =>
\let equalizer => monic-is-regular m
| true=char-m : true-over-obj = char-map m => m-is-epi (Equalizer.equal {equalizer} : true-over-obj ∘ m.f = char-map m ∘ m)
| equalizer-f : Equalizer (char-map m) (char-map m) => transport (Equalizer __ (char-map m) X m) true=char-m equalizer
\in
Equalizer.equalizer-iso equalizer-f
\use \func global (X : Ob) => Hom terminal X
\use \func namePower {A : Ob} (phi : Hom A omega) : global (Power A) => p-transpose (phi ∘ terminal-prod-left.hinv)
\use \func image {B C : Ob} : Hom (Bprod (Power $ Bprod B C) B) (Power C) =>
p-transpose $ belongs {_} {Bprod B C} ∘ associator-iso.f
\use \func is-image-single {B C : Ob} : Hom (Bprod (Power $ Bprod B C) B) omega => is-singleton ∘ image
\use \func all-with-single-img {B C : Ob} : Hom (Power $ Bprod B C) (Power B) => p-transpose is-image-single
\use \func graphs {B C : Ob} : Pullback (namePower (true-over-obj {\this} {B})) (all-with-single-img {\this} {B} {C})
=> pullback (namePower (true-over-obj {\this} {B})) (all-with-single-img {\this} {B} {C})
\where {
\use \func apex (B C : Ob) : Ob => Pullback.apex {graphs {_} {B} {C} }
\use \func map {B C : Ob} : Hom (graphs.apex B C) (Power $ Bprod B C) => Pullback.pbProj2 {graphs {_} {B} {C}}
}
\use \lemma terminate {B C : Ob} {f : Hom B C} : terminalMap ∘ f = terminalMap => terminal-unique
\private \use \lemma eval_comm {B C : Ob} : char-map (singleton-mono C) ∘ (image ∘ prodMap graphs.map (id B)) = true-map ∘ terminalMap =>
run {
rewriteI o-assoc ,
rewrite (antitranspose-eq _ : char-map (singleton-mono C) ∘ image = belongs ∘ prodMap all-with-single-img (id B)),
rewrite o-assoc,
rewriteI (prod-id-right, pbCoh {graphs}),
rewrite prod-id-right,
rewriteI (o-assoc, antitranspose-eq _),
rewrite (o-assoc, o-assoc, terminate) idp
}
\use \func eval {B C : Ob} : Hom (Bprod (graphs.apex B C) B) C
=> pbMap {char-pullback $ singleton-mono C} (image ∘ prodMap graphs.map (id B)) terminalMap eval_comm
\private \use \func h {A B C : Ob} (f : Hom (Bprod A B) C) : Hom A (Power $ Bprod B C)
=> p-transpose (char-rel f ∘ associator-iso.hinv)
\use \lemma ptranspose-eqq-eq {A B C : Ob} (f : Hom (Bprod A B) C) : p-transpose (char-rel f) = image ∘ prodMap (h f) (id B)
=> run {
inv,
p-transpose-unique {\this} {_} {_} {char-rel f} {_},
rewrite prod-id-right,
rewriteI (o-assoc, antitranspose-eq {\this} _),
rewrite o-assoc,
rewrite (inv $ associtor-prod _ _ _, inv o-assoc, prod-id, inv $ antitranspose-eq _),
rewrite (o-assoc, Iso.hinv_f {associator-iso}, id-right) idp
}
\use \lemma singleton-is-single {C : Ob} : is-singleton ∘ singleton C = true-over-obj
=> pbCoh {char-pullback (singleton-mono C)}
\private \use \func transpose' {A B C : Ob} (f : Hom (Bprod A B) C) : Hom A (graphs.apex B C)
=> \have | step1 => pmap (`∘ f) (inv singleton-is-single) *> o-assoc
| step2 : is-image-single ∘ prodMap (h f) (id B) = is-singleton ∘ (image ∘ prodMap (h f) (id B)) => o-assoc
| step3 : all-with-single-img ∘ (h f) = p-transpose (is-image-single ∘ prodMap (h f) (id B))
=> p-transpose-unique $ unfold $ rewrite prod-id-right $ rewriteI (o-assoc, antitranspose-eq _) idp
| step4 : true-over-obj {_} {B} ∘ proj2 {_} {A} {B} = true-over-obj ∘ f
=> unfold true-over-obj $ rewrite (o-assoc, terminate, o-assoc, terminate) idp
| step5 => run {
p-transpose-unique {\this} {_} {_} {true-over-obj {_} {B} ∘ proj2 {_} {A} {B}} {namePower (true-over-obj {_} {B}) ∘ terminalMap},
rewrite (prod-id-right, inv o-assoc, inv $ antitranspose-eq _),
rewrite (o-assoc, terminate, o-assoc, o-assoc, terminate),
idp
}
\in pbMap terminalMap (h f) $ unfold (Pullback.f, Pullback.g) $ rewrite (step5, step4, step3, step2, step1, eqq-p-transpose-s _, ptranspose-eqq-eq f) idp
\private \use \lemma transpose-univ' {A B C : Ob} (f : Hom (Bprod A B) C) : f = eval ∘ prodMap (transpose' f) (id B) =>
\let lem : singleton C ∘ f = image ∘ prodMap (graphs.map ∘ transpose' f) (id B) =>
rewrite (pbBeta2 {graphs}, eqq-p-transpose-s _) (ptranspose-eqq-eq _)
\in
pbEta {char-pullback (singleton-mono C)}
(rewrite (inv o-assoc, pbBeta1 {char-pullback (singleton-mono C)}) $ rewrite (o-assoc, inv $ prod-id-right _ _) lem)
terminal-unique
\private \use \lemma transpose-unique' {A B C : Ob} {f : Hom (Bprod A B) C} {g : Hom A (graphs.apex B C)} (s : f = eval ∘ prodMap g (id B)) : transpose' f = g
=> graphs.pbEta terminal-unique $ run {
unfold,
rewrite (pbBeta2 {graphs}),
unfold h, inv,
p-transpose-unique {\this} {_} {_} {eq C ∘ prodMap f (id C) ∘ hinv {associator-iso}} {pbProj2 ∘ g},
\have | step1 : singleton C ∘ f = image ∘ (prodMap (graphs.map {_} {B} {C} ∘ g) (id B))
=> rewrite (s, inv o-assoc, pbBeta1 {char-pullback (singleton-mono C)}, o-assoc, inv $ prod-id-right _ _) idp
| step2 : char-rel f = belongs {_} {Bprod B C} ∘ prodMap (graphs.map ∘ g) (id (Bprod B C)) ∘ associator
=> run {
transpose-inj,
rewrite (inv $ eqq-p-transpose-s _, step1),
p-transpose-unique {\this} {_} {_} {belongs ∘ prodMap (graphs.map ∘ g) (id (Bprod B C)) ∘ associator} {image ∘ prodMap (graphs.map ∘ g) (id B)},
rewrite {2} (prod-id-right _ _),
rewriteI o-assoc,
rewrite (inv $ antitranspose-eq _ : belongs ∘ prodMap image (id C) = belongs ∘ associator-iso.f),
rewrite {2} o-assoc ,
rewrite (inv $ associtor-prod _ _ _, prod-id),
o-assoc
},
rewrite step2,
rewrite (o-assoc, associator-iso.f_hinv, id-right),
idp
}
\use \func exp-adjoint (B : Ob) : RightAdjointCoreflection \this \this (bprodFunctorRight B) \cowith
| coreflection C => \new Coreflection (bprodFunctorRight B) C {
| Coreflected => graphs.apex B C
| corefl-map => eval
| isCoreflection => \new QEquiv {
| ret => transpose'
| ret_f _ => transpose-unique' idp
| f_sec g => inv $ transpose-univ' g
}
}
\default exp (B : Ob) : isExponential {\this} B => RightAdjointCoreflection.toAdjoint (exp-adjoint B)
}
\lemma sigma-prop-ext {A : \Prop} (a : A) : A = (\Sigma) => exts (\lam _ => (), \lam _ => a)
\lemma sigma-prop-ext-inv {A : \Prop} (eq : A = (\Sigma)) : A => propExt.conv eq ()
\open PrecatWithTerminal
\open SetCartesianClosed
\instance SetTopos : ToposPrecat \Set
| FinCompletePrecat => SetBicat
| CartesianClosedPrecat => SetCartesianClosed
| subobj-classifier => \Prop
| true-map => \lam _ => \Sigma
| char-map => IsElement
| char-pullback m => \new Pullback {
| pbCoh => exts (\lam _ => sigma-prop-ext (SetTopos.isContained _ idp))
| pbMap {_} p1 _ eq =>
\lam w1 => cases (isElement-char {_} {_} {_} {_} {p1} {eq} w1) \with {
| SetTopos.isContained a p => a
}
| pbBeta1 {_} {p1} {_} {eq} => ext (\lam w1 => cases (isElement-char {_} {_} {_} {_} {p1} {eq} w1) \with {
| SetTopos.isContained a p => p
})
| pbBeta2 => terminal-unique {SetBicat}
| pbEta {_} {h1} {h2} eq _ => ext (\lam x => \let s : Mono.f {m} (h1 x) = Mono.f {m} (h2 x) => path (\lam i => (eq @ i) x) \in mono-is-inj m s)
}
| char-unique {S} {_} {m} {phi} pullback =>
ext (\lam b =>
ext (\lam p =>
\let preimage : terminal.apex -> S => pbMap {pullback} (name' b) (terminalMap {SetBicat}) (unfold (unfold name' $ exts (\lam _ => sigma-prop-ext p))) \in
SetTopos.isContained (unname' preimage)
(\let b-image : Mono.f {m} ∘ {SetBicat} preimage = name' b => pbBeta1 {pullback} \in name-inj
(rewriteI (name-f (Mono.f {m})) $ rewrite (global-elements-iso.f_ret preimage) b-image)),
\let ss : phi ∘ {SetBicat} (Mono.f {m}) = terminalMap ∘ {SetBicat} true-map => pbCoh {pullback}
| ss-impl (x : S) : phi (Mono.f {m} x) = (\Sigma) => path (\lam i => (ss @ i) x) \in
\lam c => cases c \with {
| SetTopos.isContained a p => rewriteI p $ sigma-prop-ext-inv (ss-impl a)
}
))
\where {
\func mono-is-inj {A B : SetBicat} (m : Mono {SetBicat} {A} {B}) : IsInj m.f => \lam {a} {b} p =>
run {
name-inj,
m.isMono,
rewrite (name-f m.f a, name-f m.f b),
pmap name' p
}
\data IsElement {A B : SetBicat} (m : Mono {SetBicat} {A} {B}) (b : B)
| isContained (a : A) (m.f a = b)
\where {
\use \level isProp {A B : SetBicat} (m : Mono {SetBicat} {A} {B}) (b : B) (x y : IsElement m b) : x = y
\elim x, y
| isContained a p, isContained c p1 =>
\let a=c : a = c => mono-is-inj m (p *> inv p1)
| p=p1 : transport {A} (\lam (x : A) => m.f x = b) a=c p = p1 => prop-isProp _ _
\in \case\elim a, \elim c, \elim p, \elim p1, \elim a=c, \elim p=p1 \with {
| a, c, _, _, idp, idp => idp
}
}
\func isElement-char {S B : SetBicat} {m : Mono {SetBicat} {S} {B}} {w : SetBicat} {p1 : w -> B}
{eq : (\lam x => IsElement m (p1 x)) = (\lam _ => \Sigma)} (x : w) : IsElement m (p1 x) =>
\let s : IsElement m (p1 x) = (\Sigma) => path (\lam i => (eq @ i) x) \in
sigma-prop-ext-inv s
}