{-

Axiomatization of shapes. Postulates a type of shapes, types of homomorphisms between
shapes, and the interval shape.

-}
module axiom.shape where

open import basic
open import axiom.funext

private variable  : Level

infixl 3 _▷⟨_⟩ _^_

------------------------------------------------------------------------------------------
-- Shapes.
------------------------------------------------------------------------------------------

postulate
  --↓ We postulate a universe of shapes.
  --↓ For the equivariant model in cartesian cubical sets, we take Shape to be ℕ and
  --↓ ⟨ n ⟩ to be the n-cube 𝕀ⁿ.

  Shape : Type
  ⟨_⟩ : Shape  Type

  --↓ We postulate a type of homomorphisms between each pair of shapes.
  --↓ For the equivariant model in cartesian cubical sets, the shape homomorphisms are the
  --↓ automorphisms of cubes.

  --↓ For the formalization we do not need that the shape morphisms are closed under
  --↓ composition and identities, but closing under these does not affect the
  --↓ construction. We also do not need that shape morphisms are isomorphisms as in the
  --↓ case of the equivariant model structure on cartesian cubes, but they are constrained
  --↓ to be isomorphism-like by the axioms on cofibrations.

  Shape[_,_] : Shape  Shape  Type
  ⟪_⟫ : {I J : Shape}  Shape[ I , J ]   I    J 

  --↓ Interval shape.
  --↓ The interval shape is used to define path types and thus equivalences and anything
  --↓ that depends on equivalences.

  --↓ In the equivariant model in cartesian cubical sets, this is the shape encoding the
  --↓ 1-cube. In that case every shape is a power of the interval, but the construction
  --↓ does not require that the shapes are generated in this way (nor that shapes are
  --↓ closed under products).

  𝕚 : Shape

--↓ Notation for the interval type.

𝕀 : Type
𝕀 =  𝕚 

postulate
  --↓ We postulate that the interval has two distinct elements (the *endpoints*).

  𝕚0 : 𝕀
  𝕚1 : 𝕀
  0≠1 : {A : Type }  𝕚0  𝕚1  A

--↓ Notation for context extension by a shape.

_▷⟨_⟩ :  {}  Type   Shape  Type 
Γ ▷⟨ S  = Γ ×  S 

--↓ Notation for context extension by a copy of the interval.

_▷𝕀 :  {}  Type   Type 
Γ ▷𝕀 = Γ ▷⟨ 𝕚 

postulate
  --↓ We postulate that the type of shapes and the type of homomorphisms between any two
  --↓ shapes are flat-modal, i.e. "discrete".

  --↓ In the motivating cartesian cubical set semantics, this means they are discrete
  --↓ cubical sets, which is indeed the case for the equivariant model: the type of shapes
  --↓ is the *set* ℕ and Shape[ m , n ] is the *set* of automorphisms from the m-cube to the
  --↓ n-cube.

  ShapeIsDiscrete : {A : Shape  Type }
     ((@S : Shape)  A S)  ((S : Shape)  A S)

  ShapeIsDiscrete-β : {A : Shape  Type } (f : (@S : Shape)  A S)
    (@S : Shape)  ShapeIsDiscrete f S  f S

  {-# REWRITE ShapeIsDiscrete-β #-}

  ShapeHomIsDiscrete : {@S T : Shape} {A : Shape[ S , T ]  Type }
     ((@σ : Shape[ S , T ])  A σ)  ((σ : Shape[ S , T ])  A σ)

  ShapeHomIsDiscrete-β : {@S T : Shape} {A : Shape[ S , T ]  Type }
    (f : (@σ : Shape[ S , T ])  A σ)
    (@σ : Shape[ S , T ])  ShapeHomIsDiscrete f σ  f σ

  {-# REWRITE ShapeHomIsDiscrete-β #-}

------------------------------------------------------------------------------------------
-- Convenient notation for exponentiation by a shape.
------------------------------------------------------------------------------------------

--↓ Exponentiation by a shape.

_^_ :  {} (Γ : Type ) (S : Shape)  Type 
Γ ^ S =  S   Γ

--↓ Functorial action of exponentiation by a shape.

_`^_ :  { ℓ'} {Γ : Type } {Γ' : Type ℓ'}
  (ρ : Γ  Γ') (S : Shape)  (Γ ^ S  Γ' ^ S)
(ρ `^ S) = ρ ∘_

--↓ Unit and counit transformations for the adjunction between product with (_▷ S) and
--↓ exponentation by (_^ S) a shape.

^-unit :  {} (S : Shape) {Γ : Type }  Γ  Γ ▷⟨ S  ^ S
^-unit S = curry id

^-counit :  {} (S : Shape) {Γ : Type }  Γ ^ S ▷⟨ S   Γ
^-counit S = uncurry _$_

------------------------------------------------------------------------------------------
-- Notation for interval endpoints.
-- Using Agda's support for natural number literal overloading, we can write 0 and 1 for
-- the endpoints of the interval shape.
------------------------------------------------------------------------------------------

private
  isEndpoint : (m : )  Type
  isEndpoint 0 = 𝟙
  isEndpoint 1 = 𝟙
  isEndpoint (suc (suc _)) = 𝟘

  𝕀fromℕ : (n : )  {{_ : isEndpoint n}}  𝕀
  𝕀fromℕ 0 = 𝕚0
  𝕀fromℕ 1 = 𝕚1

instance
  Num𝕀 : Number 𝕀
  Num𝕀 .Number.Constraint = isEndpoint
  Num𝕀 .Number.fromNat = 𝕀fromℕ