Natural.algebra

-- โ„•-algebras, in the IsXXX style: structure on a small carrier as a
-- ๐•Œ-family. An โ„•-algebra is a point and an endomap โ€” no laws โ€” and a
-- homomorphism is a map commuting with both, its two laws stated with
-- Id so hom-ness is itself a code. โ„• with (Z, S) is the INITIAL such
-- algebra: natAlgInitial builds the fold into any algebra, and
-- natAlgHomUnique shows any two homs out of โ„• agree โ€” pointwise
-- first, then at function level through prelude's funext (a theorem
-- here: extensional theory).

import Core.id (Id, idToEq, eqToId)
import Core.prelude (funext)

IsNatAlgebra : ๐•Œ โ†’ ๐•Œ
IsNatAlgebra = ฮปA. (z : A) ร— A โ†’ A

NatAlgHom : (A B : ๐•Œ) โ†’ IsNatAlgebra A โ†’ IsNatAlgebra B โ†’ ๐•Œ
  using (Natural.algebra.IsNatAlgebra.unfold)
NatAlgHom =
  ฮปA B a b. (h : A โ†’ B) ร— Id _ (h (a .ฯ€โ‚)) (b .ฯ€โ‚) ร— ((x : A) โ†’ Id _ (h (a .ฯ€โ‚‚ x)) (b .ฯ€โ‚‚ (h x)))

-- โ„• is an โ„•-algebra (S eta-expanded: constructors are not functions).
natAlg : IsNatAlgebra โ„• using (Natural.algebra.IsNatAlgebra.unfold)
natAlg = Z, ฮปn. S n

-- The fold: iterate the algebra's endomap from its point.
natFold : (A : ๐•Œ) โ†’ IsNatAlgebra A โ†’ โ„• โ†’ A using (Natural.algebra.IsNatAlgebra.unfold)
natFold = ฮปA a n. โ„•-elim (a .ฯ€โ‚) (k ih. a .ฯ€โ‚‚ ih) n

-- EXISTENCE: the fold is a homomorphism into any algebra โ€” both laws
-- are ฮดฮฒ-computations (โ„•-elim at Z and at S), so each โ‹† is free.
natAlgInitial : (A : ๐•Œ) (a : IsNatAlgebra A) โ†’ NatAlgHom _ _ natAlg a
  using (Core.id.Id.eq,
    Natural.algebra.IsNatAlgebra.unfold,
    Natural.algebra.NatAlgHom.unfold,
    Natural.algebra.natAlg.eq,
    Natural.algebra.natFold.eq)
natAlgInitial = ฮปA a. natFold _ a, eqToId (natFold _ a Z) _ โ‹†, ฮปx. eqToId (natFold _ a (S x)) _ โ‹†

-- UNIQUENESS: any two homomorphisms out of โ„• agree on every point, by
-- induction. Each case let-binds the homs' laws (reflected from Id)
-- as hypotheses; the base joins at a's point, the step joins at
-- a's endomap of the induction hypothesis' common value.
natAlgHomUnique : (A : ๐•Œ)
  (a : IsNatAlgebra A)
  (f g : NatAlgHom _ _ natAlg a)
  (n : โ„•)
  โ†’ f .ฯ€โ‚ n โ‰ก g .ฯ€โ‚ n
  using (hyp.rw,
    Core.id.Id.eq,
    Core.id.Id.unfold,
    Natural.algebra.IsNatAlgebra.unfold,
    Natural.algebra.NatAlgHom.unfold,
    Natural.algebra.natAlg.eq)
natAlgHomUnique =
  ฮปA a f g n. โ„•-elim
    let hf = idToEq _ (f .ฯ€โ‚ Z) (a .ฯ€โ‚) (f .ฯ€โ‚‚ .ฯ€โ‚)
        hg = idToEq _ (g .ฯ€โ‚ Z) (a .ฯ€โ‚) (g .ฯ€โ‚‚ .ฯ€โ‚)
        โ‹†
    k ih. let hf = idToEq _ (f .ฯ€โ‚ (S k)) (a .ฯ€โ‚‚ (f .ฯ€โ‚ k)) (f .ฯ€โ‚‚ .ฯ€โ‚‚ k)
              hg = idToEq _ (g .ฯ€โ‚ (S k)) (a .ฯ€โ‚‚ (g .ฯ€โ‚ k)) (g .ฯ€โ‚‚ .ฯ€โ‚‚ k)
              f .ฯ€โ‚ (S k) โ‰กโŸจ hf โŸฉ a .ฯ€โ‚‚ (f .ฯ€โ‚ k) โ‰กโŸจ ih โŸฉ a .ฯ€โ‚‚ (g .ฯ€โ‚ k) โ‰กโŸจ hg โŸฉ g .ฯ€โ‚ (S k)
    n

-- and at FUNCTION level, one funext away.
natAlgHomUniqueFun : (A : ๐•Œ) (a : IsNatAlgebra A) (f g : NatAlgHom _ _ natAlg a) โ†’ f .ฯ€โ‚ โ‰ก g .ฯ€โ‚
  using (Natural.algebra.NatAlgHom.unfold)
natAlgHomUniqueFun = ฮปA a f g. funext (natAlgHomUnique _ _ f g)