Skip to content

1. Paths

This is a literate rzk file:

#lang rzk-1

Path induction

We define path induction in terms of the built-in J rule, so that we can apply it like any other function.

#define ind-path
  ( A : U)
  ( a : A)
  ( C : (x : A) → (a = x) → U)
  ( d : C a refl)
  ( x : A)
  ( p : a = x)
  : C x p
  := idJ (A , a , C , d , x , p)

Some basic path algebra

#section path-algebra

#variable A : U
#variables x y z : A

Path reversal

#def rev
  ( p : x = y)
  : y = x
  :=
  ind-path A x
    ( \ y' p' → y' = x)
    ( refl)
    ( y)
    ( p)

Path concatenation

We take path concatenation defined by induction on the second path variable as our main definition.

#def concat
  ( p : x = y)
  ( q : y = z)
  : x = z
  :=
  ind-path A y
    ( \ z' q' → (x = z'))
    ( p)
    ( z)
    ( q)

We also introduce a version defined by induction on the first path variable, for situations where it is easier to induct on the first path.

#def concat'
  ( p : x = y)
  : ( y = z)
  → ( x = z)
  :=
  ind-path A x
    ( \ y' p' → (y' = z) → (x = z))
    ( \ q' → q')
    ( y)
    ( p)

#end path-algebra

Some basic coherences in path algebra

#section basic-path-coherence

#variable A : U
#variables w x y z : A

#def rev-rev
  ( p : x = y)
  : rev A y x (rev A x y p) = p
  :=
  ind-path A x
    ( \ y' p' → (rev A y' x (rev A x y' p')) = p')
    ( refl)
    ( y)
    ( p)

Left unit law for path concatenation

The left unit law for path concatenation does not hold definitionally due to our choice of definition.

#def left-unit-concat
  ( p : x = y)
  : concat A x x y refl p = p
  :=
  ind-path A x
    ( \ y' p' → (concat A x x y' refl p') = p')
    ( refl)
    ( y)
    ( p)

Associativity of path concatenation

#def associative-concat
  ( p : w = x)
  ( q : x = y)
  ( r : y = z)
  : concat A w y z (concat A w x y p q) r
  = concat A w x z p (concat A x y z q r)
  :=
    ind-path A y
      ( \ z' r' 
        concat A w y z' (concat A w x y p q) r'
      = concat A w x z' p (concat A x y z' q r'))
      ( refl)
      ( z)
      ( r)

#def rev-associative-concat
  ( p : w = x)
  ( q : x = y)
  ( r : y = z)
  : concat A w x z p (concat A x y z q r)
  = concat A w y z (concat A w x y p q) r
  :=
    ind-path A y
      ( \ z' r' 
          concat A w x z' p (concat A x y z' q r')
        = concat A w y z' (concat A w x y p q) r')
      ( refl)
      ( z)
      ( r)

#def right-inverse-concat
  ( p : x = y)
  : concat A x y x p (rev A x y p) = refl
  :=
    ind-path A x
      ( \ y' p' → concat A x y' x p' (rev A x y' p') = refl)
      ( refl)
      ( y)
      ( p)

#def left-inverse-concat
  ( p : x = y)
  : concat A y x y (rev A x y p) p = refl
  :=
    ind-path A x
      ( \ y' p' → concat A y' x y' (rev A x y' p') p' = refl)
      ( refl)
      ( y)
      ( p)

Concatenation of two paths with common codomain

Concatenation of two paths with common codomain; defined using concat and rev.

#def zig-zag-concat
  ( p : x = y)
  ( q : z = y)
  : x = z
  := concat A x y z p (rev A z y q)

Concatenation of two paths with common domain

Concatenation of two paths with common domain; defined using concat and rev.

#def zag-zig-concat
  ( p : y = x)
  ( q : y = z)
  : x = z
  := concat A x y z (rev A y x p) q

#def right-cancel-concat
  ( p q : x = y)
  ( r : y = z)
  : ( concat A x y z p r = concat A x y z q r)
  → ( p = q)
  :=
    ind-path A y
      ( \ z' r' 
          ( concat A x y z' p r' = concat A x y z' q r')
        → ( p = q))
      ( \ H → H)
      ( z)
      ( r)

#end basic-path-coherence

Some derived coherences in path algebra

The statements or proofs of the following path algebra coherences reference one of the path algebra coherences defined above.

#section derived-path-coherence
#variable A : U
#variables x y z : A

#def rev-concat
  ( p : x = y)
  ( q : y = z)
  : rev A x z (concat A x y z p q)
  = concat A z y x (rev A y z q) (rev A x y p)
  :=
    ind-path A y
      ( \ z' q' 
          rev A x z' (concat A x y z' p q')
        = concat A z' y x (rev A y z' q') (rev A x y p))
      ( rev
          ( y = x)
          ( concat A y y x refl (rev A x y p))
          ( rev A x y p)
          ( left-unit-concat A y x (rev A x y p)))
      ( z)
      ( q)

Postwhiskering paths of paths

#def concat-eq-left
  ( p q : x = y)
  ( H : p = q)
  ( r : y = z)
  : concat A x y z p r
  = concat A x y z q r
  :=
    ind-path A y
      ( \ z' r' → (concat A x y z' p r') = (concat A x y z' q r'))
      ( H)
      ( z)
      ( r)

Prewhiskering paths of paths

Prewhiskering paths of paths is much harder.

#def concat-eq-right
  ( p : x = y)
  : ( q : y = z)
( r : y = z)
( H : q = r)
  → concat A x y z p q
  = concat A x y z p r
  :=
    ind-path A x
      ( \ y' p' →
        ( q : y' = z)
( r : y' = z)
( H : q = r)
      → ( concat A x y' z p' q) = (concat A x y' z p' r))
      ( \ q r H 
        concat
          ( x = z)
          ( concat A x x z refl q)
          ( r)
          ( concat A x x z refl r)
          ( concat (x = z) (concat A x x z refl q) q r (left-unit-concat A x z q) H)
          ( rev (x = z) (concat A x x z refl r) r (left-unit-concat A x z r)))
      ( y)
      ( p)

Identifying the two definitions of path concatenation

#def concat-concat'
  ( p : x = y)
  : ( q : y = z)
  → concat A x y z p q
  = concat' A x y z p q
  :=
    ind-path A x
      ( \ y' p' →
          ( q' : y' =_{A} z)
        → ( concat A x y' z p' q') =_{x =_{A} z} concat' A x y' z p' q')
      ( \ q' → left-unit-concat A x z q')
      ( y)
      ( p)

#def concat'-concat
  ( p : x = y)
  ( q : y = z)
  : concat' A x y z p q
  = concat A x y z p q
  :=
    rev
      ( x = z)
      ( concat A x y z p q)
      ( concat' A x y z p q)
      ( concat-concat' p q)

This is easier to prove for concat' than for concat.

#def alt-triangle-rotation
  ( p : x = z)
  ( q : x = y)
  : ( r : y = z)
( H : p = concat' A x y z q r)
  → concat' A y x z (rev A x y q) p = r
  :=
    ind-path A x
      ( \ y' q' →
        ( r' : y' =_{A} z)
( H' : p = concat' A x y' z q' r')
      → ( concat' A y' x z (rev A x y' q') p) = r')
      ( \ r' H' → H')
      ( y)
      ( q)

The following needs to be outside the previous section because of the usage of concat-concat' A y x.

#end derived-path-coherence

#def triangle-rotation
  ( A : U)
  ( x y z : A)
  ( p : x = z)
  ( q : x = y)
  ( r : y = z)
  ( H : p = concat A x y z q r)
  : concat A y x z (rev A x y q) p = r
  :=
    concat
      ( y = z)
      ( concat A y x z (rev A x y q) p)
      ( concat' A y x z (rev A x y q) p)
      ( r)
      ( concat-concat' A y x z (rev A x y q) p)
      ( alt-triangle-rotation
        ( A) (x) (y) (z) (p) (q) (r)
        ( concat
          ( x = z)
          ( p)
          ( concat A x y z q r)
          ( concat' A x y z q r)
          ( H)
          ( concat-concat' A x y z q r)))

Application of functions to paths

#def ap
  ( A B : U)
  ( x y : A)
  ( f : A → B)
  ( p : x = y)
  : ( f x = f y)
  := ind-path (A) (x) (\ y' p' → (f x = f y')) (refl) (y) (p)

#def ap-rev
  ( A B : U)
  ( x y : A)
  ( f : A → B)
  ( p : x = y)
  : ( ap A B y x f (rev A x y p)) = (rev B (f x) (f y) (ap A B x y f p))
  :=
    ind-path A x
      ( \ y' p' 
        ap A B y' x f (rev A x y' p') = rev B (f x) (f y') (ap A B x y' f p'))
      ( refl)
      ( y)
      ( p)

#def ap-concat
  ( A B : U)
  ( x y z : A)
  ( f : A → B)
  ( p : x = y)
  ( q : y = z)
  : ( ap A B x z f (concat A x y z p q))
  = ( concat B (f x) (f y) (f z) (ap A B x y f p) (ap A B y z f q))
  :=
    ind-path A y
      ( \ z' q' 
        ( ap A B x z' f (concat A x y z' p q'))
      = ( concat B (f x) (f y) (f z') (ap A B x y f p) (ap A B y z' f q')))
      ( refl)
      ( z)
      ( q)

#def rev-ap-rev
  ( A B : U)
  ( x y : A)
  ( f : A → B)
  ( p : x = y)
  : ( rev B (f y) (f x) (ap A B y x f (rev A x y p))) = (ap A B x y f p)
  :=
    ind-path A x
      ( \ y' p' 
        ( rev B (f y') (f x) (ap A B y' x f (rev A x y' p')))
      = ( ap A B x y' f p'))
      ( refl)
      ( y)
      ( p)

The following is for a specific use.

#def concat-ap-rev-ap-id
  ( A B : U)
  ( x y : A)
  ( f : A → B)
  ( p : x = y)
  : ( concat
      ( B) (f y) (f x) (f y)
      ( ap A B y x f (rev A x y p))
      ( ap A B x y f p))
  = ( refl)
  :=
    ind-path A x
      ( \ y' p' 
        ( concat
          ( B) (f y') (f x) (f y')
          ( ap A B y' x f (rev A x y' p')) (ap A B x y' f p'))
      = ( refl))
      ( refl)
      ( y)
      ( p)

#def ap-id
  ( A : U)
  ( x y : A)
  ( p : x = y)
  : ( ap A A x y (identity A) p) = p
  := ind-path (A) (x) (\ y' p' → (ap A A x y' (\ z → z) p') = p') (refl) (y) (p)

Application of a function to homotopic paths yields homotopic paths.

#def ap-eq
  ( A B : U)
  ( x y : A)
  ( f : A → B)
  ( p q : x = y)
  ( H : p = q)
  : ap A B x y f p
  = ap A B x y f q
  :=
    ind-path
      ( x = y)
      ( p)
      ( \ q' H' → (ap A B x y f p) = (ap A B x y f q'))
      ( refl)
      ( q)
      ( H)

#def ap-comp
  ( A B C : U)
  ( x y : A)
  ( f : A → B)
  ( g : B → C)
  ( p : x = y)
  : ( ap A C x y (comp A B C g f) p)
  = ( ap B C (f x) (f y) g (ap A B x y f p))
  :=
    ind-path
      ( A)
      ( x)
      ( \ y' p' 
        ( ap A C x y' (\ z → g (f z)) p')
      = ( ap B C (f x) (f y') g (ap A B x y' f p')))
      ( refl)
      ( y)
      ( p)

#def rev-ap-comp
  ( A B C : U)
  ( x y : A)
  ( f : A → B)
  ( g : B → C)
  ( p : x = y)
  : ( ap B C (f x) (f y) g (ap A B x y f p))
  = ( ap A C x y (comp A B C g f) p)
  :=
    rev
      ( g ( f x) = g (f y))
      ( ap A C x y (\ z → g (f z)) p)
      ( ap B C (f x) (f y) g (ap A B x y f p))
      ( ap-comp A B C x y f g p)

Transport

#section transport

#variable A : U
#variable B : A → U

Transport in a type family along a path in the base

#def transport
  ( x y : A)
  ( p : x = y)
  ( u : B x)
  : B y
  := ind-path (A) (x) (\ y' p' → B y') (u) (y) (p)

The lift of a base path to a path from a term in the total space to its transport

#def transport-lift
  ( x y : A)
  ( p : x = y)
  ( u : B x)
  : ( x , u) =_{Σ (z : A) , B z} (y , transport x y p u)
  :=
    ind-path
      ( A)
      ( x)
      ( \ y' p' → (x , u) =_{Σ (z : A) , B z} (y' , transport x y' p' u))
      ( refl)
      ( y)
      ( p)

Transport along concatenated paths

#def transport-concat
  ( x y z : A)
  ( p : x = y)
  ( q : y = z)
  ( u : B x)
  : ( transport x z (concat A x y z p q) u)
  = ( transport y z q (transport x y p u))
  :=
    ind-path
      ( A)
      ( y)
      ( \ z' q' 
        ( transport x z' (concat A x y z' p q') u)
      = ( transport y z' q' (transport x y p u)))
      ( refl)
      ( z)
      ( q)

#def transport-concat-rev
  ( x y z : A)
  ( p : x = y)
  ( q : y = z)
  ( u : B x)
  : ( transport y z q (transport x y p u))
  = ( transport x z (concat A x y z p q) u)
  :=
    ind-path
      ( A)
      ( y)
      ( \ z' q' 
        ( transport y z' q' (transport x y p u))
      = ( transport x z' (concat A x y z' p q') u))
      ( refl)
      ( z)
      ( q)

Transport along homotopic paths

#def transport2
  ( x y : A)
  ( p q : x = y)
  ( H : p = q)
  ( u : B x)
  : ( transport x y p u) = (transport x y q u)
  :=
    ind-path
      ( x = y)
      ( p)
      ( \ q' H' → (transport x y p u) = (transport x y q' u))
      ( refl)
      ( q)
      ( H)

Transport along a loop

#def transport-loop
  ( a : A)
  ( b : B a)
  : ( a = a) → B a
  := \ p → (transport a a p b)
#end transport

Dependent application

#def apd
  ( A : U)
  ( B : A → U)
  ( x y : A)
  ( f : (z : A) → B z)
  ( p : x = y)
  : ( transport A B x y p (f x)) = f y
  :=
    ind-path
      ( A)
      ( x)
      ( ( \ y' p' → (transport A B x y' p' (f x)) = f y'))
      ( refl)
      ( y)
      ( p)

Higher-order concatenation

For convenience, we record lemmas for higher-order concatenation here.

#section higher-concatenation
#variable A : U

#def triple-concat
  ( a0 a1 a2 a3 : A)
  ( p1 : a0 = a1)
  ( p2 : a1 = a2)
  ( p3 : a2 = a3)
  : a0 = a3
  := concat A a0 a1 a3 p1 (concat A a1 a2 a3 p2 p3)

#def quadruple-concat
  ( a0 a1 a2 a3 a4 : A)
  ( p1 : a0 = a1)
  ( p2 : a1 = a2)
  ( p3 : a2 = a3)
  ( p4 : a3 = a4)
  : a0 = a4
  := triple-concat a0 a1 a2 a4 p1 p2 (concat A a2 a3 a4 p3 p4)

#def quintuple-concat
  ( a0 a1 a2 a3 a4 a5 : A)
  ( p1 : a0 = a1)
  ( p2 : a1 = a2)
  ( p3 : a2 = a3)
  ( p4 : a3 = a4)
  ( p5 : a4 = a5)
  : a0 = a5
  := quadruple-concat a0 a1 a2 a3 a5 p1 p2 p3 (concat A a3 a4 a5 p4 p5)

#def alternating-quintuple-concat
  ( a0 : A)
  ( a1 : A) (p1 : a0 = a1)
  ( a2 : A) (p2 : a1 = a2)
  ( a3 : A) (p3 : a2 = a3)
  ( a4 : A) (p4 : a3 = a4)
  ( a5 : A) (p5 : a4 = a5)
  : a0 = a5
  := quadruple-concat a0 a1 a2 a3 a5 p1 p2 p3 (concat A a3 a4 a5 p4 p5)

#def 12ary-concat
  ( a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 : A)
  ( p1 : a0 = a1)
  ( p2 : a1 = a2)
  ( p3 : a2 = a3)
  ( p4 : a3 = a4)
  ( p5 : a4 = a5)
  ( p6 : a5 = a6)
  ( p7 : a6 = a7)
  ( p8 : a7 = a8)
  ( p9 : a8 = a9)
  ( p10 : a9 = a10)
  ( p11 : a10 = a11)
  ( p12 : a11 = a12)
  : a0 = a12
  :=
    quintuple-concat
      a0 a1 a2 a3 a4 a12
      p1 p2 p3 p4
      ( quintuple-concat
        a4 a5 a6 a7 a8 a12
        p5 p6 p7 p8
        ( quadruple-concat
          a8 a9 a10 a11 a12
          p9 p10 p11 p12))

The following is the same as above but with alternating arguments.

#def alternating-12ary-concat
  ( a0 : A)
  ( a1 : A) (p1 : a0 = a1)
  ( a2 : A) (p2 : a1 = a2)
  ( a3 : A) (p3 : a2 = a3)
  ( a4 : A) (p4 : a3 = a4)
  ( a5 : A) (p5 : a4 = a5)
  ( a6 : A) (p6 : a5 = a6)
  ( a7 : A) (p7 : a6 = a7)
  ( a8 : A) (p8 : a7 = a8)
  ( a9 : A) (p9 : a8 = a9)
  ( a10 : A) (p10 : a9 = a10)
  ( a11 : A) (p11 : a10 = a11)
  ( a12 : A) (p12 : a11 = a12)
  : a0 = a12
  :=
    12ary-concat
      a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12
      p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12

#end higher-concatenation

Higher-order coherences

#def rev-refl-id-triple-concat
  ( A : U)
  ( x y : A)
  ( p : x = y)
  : triple-concat A y x x y (rev A x y p) refl p = refl
  :=
    ind-path
      ( A)
      ( x)
      ( \ y' p' → triple-concat A y' x x y' (rev A x y' p') refl p' = refl)
      ( refl)
      ( y)
      ( p)

#def ap-rev-refl-id-triple-concat
  ( A B : U)
  ( x y : A)
  ( f : A → B)
  ( p : x = y)
  : ( ap A B y y f (triple-concat A y x x y (rev A x y p) refl p)) = refl
  :=
    ind-path
      ( A)
      ( x)
      ( \ y' p' 
        ( ap A B y' y' f (triple-concat A y' x x y' (rev A x y' p') refl p'))
      = ( refl))
      ( refl)
      ( y)
      ( p)

#def ap-triple-concat
  ( A B : U)
  ( w x y z : A)
  ( f : A → B)
  ( p : w = x)
  ( q : x = y)
  ( r : y = z)
  : ( ap A B w z f (triple-concat A w x y z p q r))
  = ( triple-concat
      ( B)
      ( f w)
      ( f x)
      ( f y)
      ( f z)
      ( ap A B w x f p)
      ( ap A B x y f q)
      ( ap A B y z f r))
  :=
    ind-path
      ( A)
      ( y)
      ( \ z' r' 
        ( ap A B w z' f (triple-concat A w x y z' p q r'))
      = ( triple-concat
          ( B)
          ( f w) (f x) (f y) (f z')
          ( ap A B w x f p)
          ( ap A B x y f q)
          ( ap A B y z' f r')))
      ( ap-concat A B w x y f p q)
      ( z)
      ( r)

#def triple-concat-eq-first
  ( A : U)
  ( w x y z : A)
  ( p q : w = x)
  ( r : x = y)
  ( s : y = z)
  ( H : p = q)
  : ( triple-concat A w x y z p r s) = (triple-concat A w x y z q r s)
  := concat-eq-left A w x z p q H (concat A x y z r s)

#def triple-concat-eq-second
  ( A : U)
  ( w x y z : A)
  ( p : w = x)
  ( q r : x = y)
  ( s : y = z)
  ( H : q = r)
  : ( triple-concat A w x y z p q s) = (triple-concat A w x y z p r s)
  :=
    ind-path
      ( x = y)
      ( q)
      ( \ r' H' 
        triple-concat A w x y z p q s = triple-concat A w x y z p r' s)
      ( refl)
      ( r)
      ( H)