{-# OPTIONS --without-K --safe #-}
module Cats.Category.Constructions.Initial where

open import Data.Product using (proj₁ ; proj₂)
open import Level

open import Cats.Category.Base

import Cats.Category.Constructions.Iso as Iso
import Cats.Category.Constructions.Unique as Unique


module Build {lo la l≈} (Cat : Category lo la l≈) where

  open Category Cat
  open Iso.Build Cat
  open Unique.Build Cat


  IsInitial : Obj  Set (lo  la  l≈)
  IsInitial  =  X  ∃!  X


  record HasInitial : Set (lo  la  l≈) where
    field
       : Obj
      isInitial : IsInitial 


    ¡ :  X    X
    ¡ X = ∃!′.arr (isInitial X)


    ¡-unique :  {X} (f :   X)  ¡ X  f
    ¡-unique {X} f = ∃!′.unique (isInitial X) _


    ⊥⇒-unique :  {X} (f g :   X)  f  g
    ⊥⇒-unique f g = ≈.trans (≈.sym (¡-unique f)) (¡-unique g)


    ⊥-unique :  {X}  IsInitial X  X  
    ⊥-unique {X} init = record
      { forth = init  .∃!′.arr
      ; back = ¡ X
      ; back-forth = ≈.trans (≈.sym (init X .∃!′.unique _)) (init X .∃!′.unique _)
      ; forth-back = ⊥⇒-unique _ _
      }


  initial-unique :  {X Y}  IsInitial X  IsInitial Y  X  Y
  initial-unique X-init Y-init
    = HasInitial.⊥-unique (record { isInitial = Y-init }) X-init


open Build public using (HasInitial)

private
  open module Build′ {lo la l≈} {C : Category lo la l≈}
    = Build C public using (IsInitial ; initial-unique)