\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.Category
\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
\func power \alias P (B : Ob) : Ob => p-exponential B
\func belongs {B : Ob} : Hom (Bprod (P B) B) omega => corefl-map {p-exponential B}
\func p-transpose {A B : Ob} (f : Hom (Bprod A B) omega) : Hom A (P B) => ret {isCoreflection {p-exponential B}} f
\func 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
\func p-transpose-unique {A B : Ob} {f : Hom (Bprod A B) omega} {g : Hom A (P B)} (comm : f = belongs ∘ prodMap g (id B))
: g = p-transpose f => Equiv.adjoint {isCoreflection {p-exponential B}} (inv comm)
\func anti-transpose {A B : Ob} (g : Hom A (P B)) : Hom (Bprod A B) omega =>
belongs ∘ (prodMap g (id B))
\func antitranspose-eq {A B : Ob} (f : Hom (Bprod B A) omega) : f = anti-transpose (p-transpose f) =>
p-transpose-univ f
\func 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)
\func internal-equality \alias eq (B : Ob) : Hom (Bprod B B) omega =>
char-map (diagonal.isSplitMono B)
\func singleton (B : Ob) : Hom B (P B) => p-transpose (eq B)
\func char-rel {B C : Ob} (f : Hom B C) : Hom (Bprod B C) omega => eq C ∘ prodMap f (id C)
\func 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} {singleton B ∘ b} $
rewrite (prod-id-right _ _, inv o-assoc, inv $ p-transpose-univ _) idp
\func 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
\where {
\func full-square {X : Ob} (b : Hom X B)
: Pullback {\this} (char-rel b) true-map X (pair (id X) b) => pullback-lemma right-square left-square
\func right-square
: Pullback {\this} {Bprod B B} {terminal} {omega} (eq B) true-map B (diagonal B) terminalMap =>
char-pullback (diagonal.isSplitMono B)
\func left-square{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
\func 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
}
\func is-singleton {B : Ob} : Hom (P B) omega => char-map (singleton-mono B)
\func true-over-obj {B : Ob} : Hom B omega => true-map ∘ terminalMap
\func 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
\func monic-is-regular {X Y : Ob} (m : Mono {\this} {X} {Y}) : Equalizer true-over-obj (char-map m) X m =>
\new Equalizer {
| 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
}
}
\func global (X : Ob) => Hom terminal X
\func name {A : Ob} (phi : Hom A omega) : global (P A) => p-transpose (phi ∘ terminal-prod-left.hinv)
\func image {B C : Ob} : Hom (Bprod (P $ Bprod B C) B) (P C) =>
p-transpose $ belongs {_} {Bprod B C} ∘ associator-iso.f
\func is-image-single {B C : Ob} : Hom (Bprod (P $ Bprod B C) B) omega => is-singleton ∘ image
\func all-with-single-img {B C : Ob} : Hom (P $ Bprod B C) (P B) => p-transpose is-image-single
\func graphs {B C : Ob} : Pullback (name (true-over-obj {\this} {B})) (all-with-single-img {\this} {B} {C}) =>
pullback (name (true-over-obj {\this} {B})) (all-with-single-img {\this} {B} {C})
\where {
\func apex (B C : Ob) : Ob => Pullback.apex {graphs {_} {B} {C} }
\func map {B C : Ob} : Hom (graphs.apex B C) (P $ Bprod B C) => Pullback.pbProj2 {graphs {_} {B} {C}}
}
\lemma terminate {B C : Ob} {f : Hom B C} : terminalMap ∘ f = terminalMap => terminal-unique
\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 comm
\where {
\func comm : 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
}
}
\func h {A B C : Ob} (f : Hom (Bprod A B) C) : Hom A (P $ Bprod B C) =>
p-transpose (char-rel f ∘ associator-iso.hinv)
\func 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
}
\lemma singleton-is-single {C : Ob} : is-singleton ∘ singleton C = true-over-obj =>
pbCoh {char-pullback (singleton-mono C)}
\func exp-adjoint (B : Ob) : RightAdjointCoreflection \this \this (bprodFunctorRight B)
\cowith
| coreflection => exp B
\where {
\func exp (B : Ob) (C : Ob) : Coreflection (bprodFunctorRight B) C \cowith
| 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
}
\func transpose' {A B C : Ob} (f : Hom (Bprod A B) C) : Hom A (graphs.apex B C) =>
pbMap terminalMap (h f) (unfold (Pullback.f, Pullback.g) $
rewrite (step5, step4, step3, step2, step1, eqq-p-transpose-s _, ptranspose-eqq-eq f) idp)
\where {
\func step1 : true-over-obj ∘ f = is-singleton ∘ (singleton C ∘ f) =>
rewriteI o-assoc $ rewrite singleton-is-single idp
\func step2 : is-image-single ∘ prodMap (h f) (id B) = is-singleton ∘ (image ∘ prodMap (h f) (id B) ) =>
rewriteI o-assoc $ idp
\func 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
\func step4 : true-over-obj {_} {B} ∘ proj2 {_} {A} {B} = true-over-obj ∘ f =>
unfold true-over-obj $ rewrite (o-assoc, terminate, o-assoc, terminate) idp
\func step5
: name (true-over-obj {_} {B}) ∘ terminalMap = p-transpose (true-over-obj {_} {B} ∘ proj2 {_} {A} {B}) =>
run {
p-transpose-unique {\this} {_} {_} {true-over-obj {_} {B} ∘ proj2 {_} {A} {B}} {name (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
}
}
\func 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
\func 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 =>
pbEta {graphs} 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},
rewrite step2, rewrite (o-assoc, associator-iso.f_hinv, id-right),
idp
})
\where {
\func 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
\func 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
}
}
}
\default exp (B : Ob) : isExponential {\this} B => RightAdjointCoreflection.toAdjointCounit (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
}