{-# OPTIONS --safe --without-K #-}
{-
A self-contained proof of the following result (found at the bottom of the file):
Any type with a binary operation that is associative, commutative, and idempotent
is 0-truncated.
Checked with Agda version 2.6.4.3.
Written 17 February 2026.
-}

infix 15 _≡_
data _≡_ {A : Set} (a : A) : A  Set where
  rfl : a  a

ap : {A B : Set} {a b : A} (f : A  B)  a  b  f a  f b
ap f rfl = rfl

infixr 20 _∙_
_∙_ : {A : Set} {a b c : A}  a  b  b  c  a  c
rfl  rfl = rfl

eq-congr : {A : Set} {a b x y : A}  a  x  b  y  a  b  x  y
eq-congr rfl rfl p = p

eq-congr-∙ : {A : Set} {a b c x y z : A}
             {h1 : a  x} {h2 : b  y} {h3 : c  z}
             (p : a  b) (q : b  c) 
             eq-congr h1 h3 (p  q)  eq-congr h1 h2 p  eq-congr h2 h3 q
eq-congr-∙ {h1 = rfl} {h2 = rfl} {h3 = rfl} p q = rfl

eq-congr-rfl : {A : Set} {a x : A} (h : a  x) 
               eq-congr h h rfl  rfl
eq-congr-rfl rfl = rfl

bla : {A : Set} {a b x y : A} (ha : a  a) (hb : b  b)
      (hax : a  x) (hby : b  y) (p : a  b) 
      eq-congr hax hby (eq-congr ha hb p)
       eq-congr (eq-congr hax hax ha) (eq-congr hby hby hb) (eq-congr hax hby p)
bla ha hb rfl rfl p = rfl

∙rfl : {A : Set} {a b : A} (p : a  b)  p  rfl  p
∙rfl rfl = rfl

rfl∙ : {A : Set} {a b : A} (p : a  b)  rfl  p  p
rfl∙ rfl = rfl

ap2 : {A B C : Set} (f : A  B  C) {a1 a2 : A} {b1 b2 : B}
       a1  a2  b1  b2  f a1 b1  f a2 b2
ap2 f rfl rfl = rfl

assoc-4 : {A : Set} {a b c d e : A}
          {p : a  b} {q : b  c} {r : c  d} {s : d  e} 
          (p  q)  (r  s)  p  (q  r)  s
assoc-4 {p = rfl} {q = rfl} {r = rfl} {s = rfl} = rfl

sym : {A : Set} {a b : A}  a  b  b  a
sym rfl = rfl

comm² : {A : Set} {a : A} {p q : a  a} (h : p  q  q  p) 
        (p  p)  (q  q)  (q  q)  (p  p)
comm² {p = p} {q = q} h = eq-congr (sym assoc-4) (sym assoc-4)
          (eq-congr (ap  x  p  x  q) (sym h))
          (ap  x  q  x  p) h)
          (eq-congr assoc-4 assoc-4 ((ap  x  x  x)) h)))

eq-congr-sym : {A : Set} {a b x y : A} {hax : a  x} {hby : b  y}
               {p : a  b} {q : x  y} 
               eq-congr hax hby p  q  p  eq-congr (sym hax) (sym hby) q
eq-congr-sym {hax = rfl} {hby = rfl} rfl = rfl

congr-∙  : {A : Set} {a b u v x y : A} (l1 : a  u) (l2 : u  x)
           (r1 : b  v) (r2 : v  y) (p : a  b) 
           eq-congr (l1  l2) (r1  r2) p  eq-congr l2 r2 (eq-congr l1 r1 p)
congr-∙ rfl rfl rfl rfl p = rfl

eq-congr-sq : {A : Set} {a b x y : A} (p : a  b) (q : a  x) (r : b  y) 
            q  eq-congr q r p  p  r
eq-congr-sq rfl rfl rfl = rfl

∙-cancel : {A : Set} {a b c : A} (p : a  b) (q1 q2 : b  c) 
           p  q1  p  q2  q1  q2
∙-cancel rfl q1 q2 h = eq-congr (rfl∙ q1) (rfl∙ q2) h

module _
  (A : Set)
  (_*_ : A  A  A)
  (idem : (a : A)  a * a  a)
  (comm : (a b : A)  a * b  b * a)
  (assoc : (a b c : A)  (a * b) * c  a * (b * c))
  (x₀ : A)
  where

  ΩA : Set
  ΩA = x₀  x₀

  *-paths : {a1 a2 b1 b2 : A}  a1  a2  b1  b2 
            a1 * b1  a2 * b2
  *-paths = ap2 _*_

  *-paths≡∙ : {a1 a2 b1 b2 : A} (p : a1  a2) (q : b1  b2) 
              *-paths p q  ap (_* b1) p  ap (a2 *_) q
  *-paths≡∙ rfl rfl = rfl

  eq-congr' : x₀ * x₀  x₀ * x₀  x₀  x₀
  eq-congr' = eq-congr (idem x₀) (idem x₀)

  *-loop : ΩA  ΩA  ΩA
  *-loop p q = eq-congr' (*-paths p q)

  f g : ΩA  ΩA
  f p = eq-congr' (ap (_* x₀) p)
  g q = eq-congr' (ap (x₀ *_) q)

  *-loop≡∙ : (p q : x₀  x₀)  *-loop p q  f p  g q
  *-loop≡∙ p q = ap eq-congr' (*-paths≡∙ _ _)
                   eq-congr-∙ (ap (_* x₀) p) (ap (x₀ *_) q)

  idem-paths : {a b : A} (p : a  b) 
               eq-congr (idem a) (idem b) (*-paths p p)  p
  idem-paths rfl = eq-congr-rfl (idem _)

  idem-loop : (p : ΩA)  *-loop p p  p
  idem-loop = idem-paths

  comm-paths : {a b x y : A} (p : a  x) (q : b  y) 
               eq-congr (comm a b) (comm x y) (*-paths p q)
                *-paths q p
  comm-paths rfl rfl = eq-congr-rfl _

  t : ΩA
  t = eq-congr' (comm x₀ x₀)

  comm-loop' : (p q : ΩA) 
              eq-congr t t (*-loop p q)  *-loop q p
  comm-loop' p q = eq-congr
    (bla (comm x₀ x₀) (comm x₀ x₀) (idem x₀) (idem x₀) (*-paths p q))
    rfl (ap eq-congr' (comm-paths p q))

  t-center : (p : ΩA)  eq-congr t t p  p
  t-center p = eq-congr (ap (eq-congr t t) (idem-loop p)) (idem-loop p) (comm-loop' p p)

  comm-loop : (p q : ΩA)  *-loop p q  *-loop q p
  comm-loop p q = eq-congr (t-center _) rfl (comm-loop' p q)

  fg-swap : (p q : ΩA)  f p  g q  f q  g p
  fg-swap p q = eq-congr (*-loop≡∙ p q) (*-loop≡∙ q p) (comm-loop p q)

  f-rfl : f rfl  rfl
  f-rfl = eq-congr-rfl _

  g-rfl : g rfl  rfl
  g-rfl = eq-congr-rfl _

  f≡g : (p : ΩA)  f p  g p
  f≡g p = eq-congr (ap (f p ∙_) g-rfl  ∙rfl _) (ap (_∙ g p) f-rfl  rfl∙ _)
           (fg-swap p rfl)

  idem-loop-ff : (p : ΩA)  f p  f p  p
  idem-loop-ff p = ap (f p ∙_) (f≡g p)  eq-congr (*-loop≡∙ p p) rfl (idem-loop p)

  ff-comm : (p q : ΩA)  f p  f q  f q  f p
  ff-comm p q = eq-congr (ap (f p ∙_) (sym (f≡g q))) (ap (f q ∙_) (sym (f≡g p)))
                (fg-swap p q)

  loop-comm : (p q : ΩA)  p  q  q  p
  loop-comm p q = eq-congr (ap2 _∙_ (idem-loop-ff p) (idem-loop-ff q))
                  (ap2 _∙_ (idem-loop-ff q) (idem-loop-ff p))
                  (comm² (ff-comm p q))

  assoc-paths : {a b c x y z : A} (p : a  x) (q : b  y) (r : c  z) 
                eq-congr (assoc a b c) (assoc x y z) (*-paths (*-paths p q) r)
                 *-paths p (*-paths q r)
  assoc-paths rfl rfl rfl = eq-congr-rfl _

  blabla : {a b c d e : A} (hab : a * b  c) (hcd : c * d  e)
           (p : a  a) (q : b  b) (r : d  d) 
           eq-congr (*-paths hab rfl  hcd) (*-paths hab rfl  hcd)
           (*-paths (*-paths p q) r) 
           eq-congr hcd hcd (*-paths (eq-congr hab hab (*-paths p q)) r)
  blabla rfl rfl p q r = rfl

  idem3 : (x₀ * x₀) * x₀  x₀
  idem3 = *-paths (idem x₀) rfl  idem x₀

  foo : (p q r : ΩA) 
        eq-congr idem3 idem3 (*-paths (*-paths p q) r)  *-loop (*-loop p q) r
  foo p q r = blabla (idem x₀) (idem x₀) p q r

  blabla' : {a b c d e : A} (hab : a * b  c) (hcd : d * c  e)
           (p : a  a) (q : b  b) (r : d  d) 
           eq-congr (*-paths rfl hab  hcd) (*-paths rfl hab  hcd)
           (*-paths r (*-paths p q)) 
           eq-congr hcd hcd (*-paths r (eq-congr hab hab (*-paths p q)))
  blabla' rfl rfl p q r = rfl

  idem3' : x₀ * (x₀ * x₀)  x₀
  idem3' = *-paths rfl (idem x₀)  idem x₀

  foo' : (p q r : ΩA) 
        eq-congr idem3' idem3' (*-paths p (*-paths q r))  *-loop p (*-loop q r)
  foo' p q r = blabla' (idem x₀) (idem x₀) q r p

  t' : ΩA
  t' = sym idem3  (assoc x₀ x₀ x₀  idem3')

  *-loop-assoc' : (p q r : ΩA) 
               eq-congr t' t' (*-loop (*-loop p q) r)  *-loop p (*-loop q r)
  *-loop-assoc' p q r = eq-congr
    (sym (congr-∙ (assoc x₀ x₀ x₀) idem3' _ idem3' _)
       sym (congr-∙ (sym idem3) _ _ _ _))
    (foo' p q r)
    (ap (eq-congr idem3' idem3') (ap (eq-congr (assoc x₀ x₀ x₀) _)
    (sym (eq-congr-sym (foo p q r)))  assoc-paths p q r))

  *-loop-rfl : (p : ΩA)  *-loop p rfl  f p
  *-loop-rfl p = *-loop≡∙ p rfl  ap (f p ∙_) g-rfl  ∙rfl (f p)

  *-loop-assoc : (p q r : ΩA)  *-loop (*-loop p q) r  *-loop p (*-loop q r)
  *-loop-assoc p q r = ∙-cancel t' _ _ (loop-comm _ _  sym (eq-congr-sq _ _ _))
                        *-loop-assoc' p q r

  ff≡f : (p : ΩA)  f (f p)  f p
  ff≡f p = eq-congr (*-loop-rfl _  ap f (*-loop-rfl p))
           (ap (*-loop p) (*-loop-rfl rfl  f-rfl)  *-loop-rfl p)
           (*-loop-assoc p rfl rfl)

  f-null : (p : ΩA)  f p  rfl
  f-null p = ∙-cancel (f p) (f p) rfl ((ap2 _∙_ (sym (ff≡f p)) (sym (ff≡f p))  idem-loop-ff (f p))  sym (∙rfl (f p)))

  Ω-null : (p : x₀  x₀)  p  rfl
  Ω-null p = sym (idem-loop-ff p)  ap2 _∙_ (f-null p) (f-null p)  ∙rfl rfl