{-# OPTIONS --without-K #-}
module Model.Product where

open import Cats.Category
open import Data.Product using (<_,_>)

open import Model.Type.Core
open import Util.HoTT.HLevel
open import Util.Prelude hiding (_×_)


infixr 5 _×_


_×_ :  {Γ} (T U : ⟦Type⟧ Γ)  ⟦Type⟧ Γ
T × U = record
  { ObjHSet = λ δ  T .ObjHSet δ ×-HSet U .ObjHSet δ
  ; eqHProp = λ where
      γ≈γ′ (x , x′) (y , y′)  T .eqHProp γ≈γ′ x y ×-HProp U .eqHProp γ≈γ′ x′ y′
  ; eq-refl = λ where
      (x , y)  T .eq-refl x , U .eq-refl y
  }


π₁ :  {Γ} {T} (U : ⟦Type⟧ Γ)  T × U  T
π₁ U = record
  { fobj = proj₁
  ; feq = λ p  proj₁
  }


π₂ :  {Γ} T {U : ⟦Type⟧ Γ}  T × U  U
π₂ T = record
  { fobj = proj₂
  ; feq = λ p  proj₂
  }


⟨_,_⟩ :  {Γ} {X T U : ⟦Type⟧ Γ}
   X  T  X  U  X  T × U
 f , g  = record
  { fobj = < f .fobj , g .fobj >
  ; feq = λ γ≈γ′  < f .feq γ≈γ′ , g .feq γ≈γ′ >
  }


instance
  hasBinaryProducts :  {Γ}  HasBinaryProducts (⟦Types⟧ Γ)
  hasBinaryProducts .HasBinaryProducts._×′_ T U = record
    { prod = T × U
    ; proj = λ where
        true  π₁ U
        false  π₂ T
    ; isProduct = λ π′  record
      { arr =  π′ true , π′ false 
      ; prop = λ where
          true  ≈⁺ λ γ x  refl
          false  ≈⁺ λ γ x  refl
      ; unique = λ {f} f-prop  ≈⁺ λ γ x
           cong₂ _,_ (f-prop true .≈⁻ γ x) (f-prop false .≈⁻ γ x)
      }
    }


open module ⟦Types⟧× {Γ}
  = HasBinaryProducts (hasBinaryProducts {Γ})
  public using
  ( ⟨_×_⟩ ) renaming
  ( ×-resp-≅ to ×-resp-≈⟦Type⟧ )