module Cat.Instances.Sets.Counterexamples.SelfDual {} where

Sets is not self-dual🔗

We show that the category of sets is not self-dual, that is, there cannot exist a path between and

import Cat.Reasoning (Sets ) as Sets
import Cat.Reasoning (Sets  ^op) as Sets^op

To show our goal, we need to find a categorical property that holds in but not in First we note that both and have an initial object.

In

_ : Initial (Sets )
_ = Sets-initial

In

Sets^op-initial : Initial (Sets  ^op)
Sets^op-initial .bot = el! (Lift _ )
Sets^op-initial .has⊥ x = hlevel 0
_ = 

Now we can observe an interesting property of the initial object of it is strict, meaning every morphism into it is in fact an isomorphism. Intuitively, if you can write a function then must itself be empty.

Sets-strict-initial : Strict-initial (Sets )
Sets-strict-initial .initial = Sets-initial
Sets-strict-initial .has-is-strict x f .inv ()
Sets-strict-initial .has-is-strict x f .inverses .invl = ext λ ()
Sets-strict-initial .has-is-strict x f .inverses .invr = ext λ x  absurd (f x .lower)

Crucially, this property is not shared by the initial object of Unfolding definitions, it says that any function is an isomorphism, or equivalently, every inhabited set is contractible. But is this is certainly false: Bool is inhabited, but not contractible, since true≠false.

¬Sets^op-strict-initial : ¬ Strict-initial (Sets  ^op)
¬Sets^op-strict-initial si = true≠false true≡false
  where

is univalent, so we invoke the propositionality of its initial object to let us work with , for convenience.

    si≡⊤ : si .initial  Sets^op-initial
    si≡⊤ = ⊥-is-prop _ Sets^op-is-category _ _

    to-iso-⊤ : (A : Set )  (Lift     A )  A Sets^op.≅ el! (Lift  )
    to-iso-⊤ A f = invertible→iso _ _ (subst (is-strict-initial (Sets  ^op)) si≡⊤ (si .has-is-strict) A f)

Using our ill-fated hypothesis, we can construct an iso between Bool and from a function Bool. From this we conclude that Bool is contractible, from which we obtain (modulo lifting) a proof of true false.

    Bool≅⊤ : el! (Lift  Bool) Sets^op.≅ el! (Lift  )
    Bool≅⊤ = to-iso-⊤ (el! (Lift _ Bool)) λ _  lift true

    Bool-is-contr : is-contr (Lift  Bool)
    Bool-is-contr = subst (is-contr  ∣_∣) (sym (Univalent.iso→path Sets^op-is-category Bool≅⊤)) (hlevel 0)

    true≡false : true  false
    true≡false = lift-inj $ is-contr→is-prop Bool-is-contr _ _

We’ve shown that a categorical property holds in and fails in but paths between categories preserve categorical properties, so we have a contradiction!

Sets≠Sets^op : ¬ (Sets   Sets  ^op)
Sets≠Sets^op p = ¬Sets^op-strict-initial (subst Strict-initial p Sets-strict-initial)