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)