module Paths where

------------------------------------------------------------------------------

import Cubical.Foundations.Prelude as Lib renaming (subst to tpt)

open import Cubical.Core.Primitives

variable
   ℓ' ℓ'' : Level
  A B C : Type 

------------------------------------------------------------------------------














------------------------------------------------------------------------------
-- The Interval Type
------------------------------------------------------------------------------
{-

I : Type

i0 i1 : I

~ : I → I
_∧_ _∨_ : I → I → I



Paths in A between
    (a : A) and (b : A)
are maps
    p : I → A
with:
- p i0 = a
- p i1 = b

Path : {ℓ : Level} (A : Type ℓ) → A → A → Type ℓ



Paths over (A : I → Type) between
    (a : A i0) and (b : A i1)
are maps
    p : (i : I) → A i
with:
- p i0 = a
- p i1 = b

PathP : {ℓ : Level} (A : I → Type ℓ) → A i0 → A i1 → Type ℓ

-}




-- `refl a` is the constant path I → A at a
refl : (a : A)  a  a
refl a i = a

-- sym p is the path p in reverse
sym : {a b : A}  a  b  b  a
sym p i = p (~ i)

-- what about transitivity?


-- funExt is pointwise equality of functions
funExt : {f g : A  B}  ((x : A)  f x  g x)  f  g
funExt α i x = α x i

-- ap applies a path to a function
ap : {a b : A}  (f : A  B)  (p : a  b)  f a  f b
ap f p i = f (p i)

-- apd applies a dependent path to a function
apd : {B : A  Type }
   (f : (x : A)  B x)
   {a b : A}  (p : a  b)
   PathP  i  B (p i)) (f a) (f b)
apd f p i = f (p i)


















------------------------------------------------------------------------------
-- Squares, Cubes, ...
------------------------------------------------------------------------------
{-

A square in A with vertices
    (a b c d : A)
is a map
    p : I × I → A
with

-  p i0 i0 = a
-  p i0 i1 = b
-  p i1 i0 = c
-  p i1 i1 = d

    b --------> d
    ∧           ∧
    |           |
    |           |
    |           |
j   a --------> c
∧
|
+-> i





A cube in A with vertices
    (a b c d e f g h : A)
is a map
    p : I × I × I → A
with
- p i0 i0 i0 = a
- p i0 i0 i1 = b
- ...

But we'll stick to squares for now...
-}

module Squares where

  private variable
    a b c d : A

  Square :  {} {A : Type }
    {a b : A} (p : a  b)
    {c d : A} (q : c  d)
    (r : a  c) (s : b  d)
     Type _
  Square {A = A} p q r s = PathP  i  Path A (r i) (s i)) p q

  lid : (p : a  b) (q : c  d) (r : a  c)
     b  d
  lid p q r i =
    hcomp  j  λ { (i = i0)  p j
                   ; (i = i1)  q j })
          (r i)






------------------------------------------------------------------------------
-- Connections and Composition
------------------------------------------------------------------------------

  const-i : (p : a  b)  Square p p (refl a) (refl b)
  const-i p i j = p j

  lower : (p : a  b)  Square p (refl b) p (refl b)
  lower p i j = p (i  j)

  upper : (p : a  b)  Square (refl a) p (refl a) p
  upper p i j = p (i  j)

  left : (p : a  b)  Square (refl a) (sym p) p (refl a)
  left p i j = p (i  ~ j)

  right : (p : a  b)  Square p (refl a) (refl a) (sym p)
  right p i j = p (~ i  j)





  symmetricSquare : (p : a  b)  (q : b  c)  Square p q p q
  symmetricSquare p q i j =
    hcomp  k 
      λ { (i = i0)  p (j  ~ k)
      ; (i = i1)  q j
      ; (j = i0)  p (i  ~ k)
      ; (j = i1)  q i
    })
    (q (i  j))




  filler : (p : a  b) (q : c  d) (r : a  c)
     Square p q r (lid p q r)
  filler p q r i j =
    hcomp  k   { (i = i0)  p (j  k)
                    ; (i = i1)  q (j  k)
                    ; (j = i0)  r i
                    -- ; (j = i1) → filler p q r i k -- recursive sorcery
                    }))
          (r i)

  infixr 5 _∙_

  _∙_ : a  b  b  c  a  c
  r  q = lid (refl (r i0)) q r



------------------------------------------------------------------------------