{-

Kan Operations for n-Truncated Types

It provides an efficient way to construct cubes in truncated types.

A draft note on this can be found online at
https://kangrongji.github.io/files/extend-operations.pdf

-}
{-# OPTIONS --safe #-}
module Cubical.Foundations.HLevels.Extend where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels

private
  variable
     : Level


-- For conveniently representing the boundary of cubes
 : I  I
 i = i  ~ i


-- TODO: Write a macro to generate these stuff.

module _
  {X : Type }
  (h : isContr X)
  {ϕ : I} where

  extend₀ :
    (x : Partial _ X)
     X [ ϕ  x ]
  extend₀ = extend h _


module _
  {X : I  Type }
  (h : (i : I)  isProp (X i))
  {ϕ : I} where

  extend₁ :
    (x : (i : I)  Partial _ (X i))
    (i : I)  X i [ ϕ   i  x i ]
  extend₁ x i = inS (hcomp  j  λ
    { (ϕ = i1)  h i (bottom i) (x i 1=1) j
    ; (i = i0)  h i (bottom i) (x i 1=1) j
    ; (i = i1)  h i (bottom i) (x i 1=1) j })
    (bottom i))
    where
    bottom : (i : I)  X i
    bottom i = isProp→PathP h (x i0 1=1) (x i1 1=1) i


module _
  {X : I  I  Type}
  (h : (i j : I)  isSet (X i j))
  {ϕ : I} where

  extend₂ :
    (x : (i j : I)  Partial _ (X i j))
    (i j : I)  X i j [ ϕ   i   j  x i j ]
  extend₂ x i j = inS (outS (extend₁PathP p i) j)
    where
    isOfHLevel₁PathP : (i : I) (a : X i i0) (b : X i i1)
       isProp (PathP  j  X i j) a b)
    isOfHLevel₁PathP i = isOfHLevelPathP' 1 (h i i1)

    extend₁PathP :
      (p : (i : I)  Partial _ (PathP _ (x i i0 1=1) (x i i1 1=1)))
      (i : I)  PathP _ (x i i0 1=1) (x i i1 1=1) [ ϕ   i  p i ]
    extend₁PathP = extend₁  i  isOfHLevel₁PathP i (x i i0 1=1) (x i i1 1=1)) {ϕ}

    p : (i : I)  Partial _ (PathP _ (x i i0 1=1) (x i i1 1=1))
    p i (i = i0) = λ j  x i j 1=1
    p i (i = i1) = λ j  x i j 1=1
    p i (ϕ = i1) = λ j  x i j 1=1


module _
  (X : I  I  I  Type)
  (h : (i j k : I)  isGroupoid (X i j k))
  {ϕ : I} where

  extend₃ :
    (x : (i j k : I)  Partial _ (X i j k))
    (i j k : I)  X i j k [ ϕ   i   j   k  x i j k ]
  extend₃ x i j k = inS (outS (extend₂PathP p i j) k)
    where
    isOfHLevel₂PathP : (i j : I) (a : X i j i0) (b : X i j i1)
       isSet (PathP  k  X i j k) a b)
    isOfHLevel₂PathP i j = isOfHLevelPathP' 2 (h i j i1)

    extend₂PathP :
      (p : (i j : I)  Partial _ (PathP _ (x i j i0 1=1) (x i j i1 1=1)))
      (i j : I)  PathP _ (x i j i0 1=1) (x i j i1 1=1) [ ϕ   i   j  p i j ]
    extend₂PathP = extend₂  i j  isOfHLevel₂PathP i j (x i j i0 1=1) (x i j i1 1=1)) {ϕ}

    p : (i j : I)  Partial _ (PathP  k  X i j k) (x i j i0 1=1) (x i j i1 1=1))
    p i j (i = i0) = λ k  x i j k 1=1
    p i j (i = i1) = λ k  x i j k 1=1
    p i j (j = i0) = λ k  x i j k 1=1
    p i j (j = i1) = λ k  x i j k 1=1
    p i j (ϕ = i1) = λ k  x i j k 1=1


private
  -- An example showing how to directly fill 3-cubes in an h-proposition.
  -- It can help when one wants to pattern match certain HITs towards some n-types.

  isProp→Cube :
    {X : Type } (h : isProp X)
    (x : (i j k : I)  Partial _ X)
    (i j k : I)  X [  i   j   k  x i j k ]
  isProp→Cube h x i j =
    extend₁  _  h) { i   j} (x i j)