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

open import Data.Unit using ()
open import Level

open import Cats.Category.Base
open import Cats.Util.Conv


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

  open Category Cat


  IsUniqueSuchThat :  {lp A B}  (A  B  Set lp)  A  B  Set (la  l≈  lp)
  IsUniqueSuchThat P f =  {g}  P g  f  g


  IsUnique :  {A B}  A  B  Set (la  l≈)
  IsUnique {A} {B} = IsUniqueSuchThat {A = A} {B}  _  )


  IsUniqueSuchThat→≈ :  {lp A B} {P : A  B  Set lp} {f}
     IsUniqueSuchThat P f
      {g h}
     P g
     P h
     g  h
  IsUniqueSuchThat→≈ unique Pg Ph = ≈.trans (≈.sym (unique Pg)) (unique Ph)


  record ∃!′ {lp A B} (P : A  B  Set lp) : Set (la  l≈  lp) where
    constructor ∃!-intro
    field
      arr : A  B
      prop : P arr
      unique : IsUniqueSuchThat P arr


  instance
    HasArrow-∃! :  {lp A B} {P : A  B  Set lp}
       HasArrow (∃!′ P) lo la l≈
    HasArrow-∃! = record { Cat = Cat ; _⃗ = ∃!′.arr }


  syntax ∃!′  f  P) = ∃![ f ] P


  ∃!″ :  {lp A B} (P : A  B  Set lp)  Set (la  l≈  lp)
  ∃!″ = ∃!′

  syntax ∃!″ {A = A} {B}  f  P) = ∃![ f  A  B ] P


  ∃! : (A B : Obj)  Set (la  l≈)
  ∃! A B = ∃![ f  A  B ] 


  ∃!→≈ :  {lp A B} {P : A  B  Set lp}
     ∃!′ P
      {g h}
     P g
     P h
     g  h
  ∃!→≈ (∃!-intro _ _ unique) = IsUniqueSuchThat→≈ unique


open Build public