Skip to content

Derivative.Examples.List

Ordered Lists as a Container

The container \( ((n : β„•) \lhd [n]) \) represents the type of ordered lists. The shape of a list is its length \( n \); such a list has \( n \) positions for data.

private
  [_] : β„• β†’ Type
  [ n ] = Fin n

List : Container β„“-zero πŸ™
List .Shape = β„•
List .Pos _ n = [ n ]

Derivative

The derivative of the list container is the container of pairs of lists.

βˆ‚List : βˆ‚β€’ List ⧟ (List βŠ— List)
βˆ‚List = βˆ‚-list-equiv where

Recall that pairs of lists have the following shapes and positions:

  _ : List βŠ— List ≑ ((β„• Γ— β„•) ◁ Ξ» _ (m , n) β†’ [ m ] ⊎ [ n ])
  _ = refl

We build an equivalence with this container in two steps. First, notice that positions \( [ n ] \) are discrete, hence \( {[ n ]}^\circ \simeq [ n ] \), and we can write \( \partial(\mathsf{List}) \) as the following:

  Listβˆ™ : Container β„“-zero πŸ™
  Listβˆ™ = (Ξ£[ n ∈ β„• ] [ n ]) ◁ Ξ» _ (n , k) β†’ [ n ] βˆ– k

  forget-isolated-pos : βˆ‚β€’ List ⧟ Listβˆ™
  forget-isolated-pos = ⧟-shape $ Sigma.Ξ£-cong-equiv-snd $ Discreteβ†’IsolatedEquiv ∘ DiscreteFin

Next, observe that pairs of lists of length \( m \) and \( n \) correspond uniquely to lists of length \( m + 1 + n \) with a hole at position \( m \). The map hole computes the position of the hole in a list of length \( m + 1 + n \), preceded by \( m \) and followed by \( n \) elements.

  open Nat using () renaming (_+_ to infixr 8 _+_)

  hole : (m n : β„•) β†’ [ m + 1 + n ]
  hole zero n = fzero
  hole (suc m) n = fsuc (hole m n)

This defines a map into the shapes of \( \partial(\mathsf{List}) \): Glue two lists of lengths \( m \) and \( n \) together, with a hole in between.

  glue : β„• Γ— β„• β†’ Ξ£[ n ∈ β„• ] [ n ]
  glue (m , n) = (m + 1 + n) , hole m n

In the other direction, split a list of length \( n \) at position \( k \) into the parts preceding and following \( k \).

  split : (n : β„•) β†’ (k : [ n ]) β†’ β„• Γ— β„•
  split (suc n) fzero = 0 , n
  split (suc n) (fsuc k) = let (m' , n') = split n k in suc m' , n'

Together, these form an equivalence of shapes.

  glue-equiv : (β„• Γ— β„•) ≃ (Ξ£[ n ∈ β„• ] [ n ])
  glue-equiv = isoToEquiv glue-iso where
    split-glue : βˆ€ m n β†’ split (m + 1 + n) (hole m n) ≑ (m , n)
    split-glue zero n = refl
    split-glue (suc m) n i = let (p , q) = split-glue m n i in suc p , q

    glue-split : βˆ€ n (k : [ n ]) β†’ glue (split n k) ≑ (n , k)
    glue-split (suc n) fzero = refl
    glue-split (suc n) (fsuc k) i = let (p , q) = glue-split n k i in suc p , fsuc q

    glue-iso : Iso _ _
    glue-iso .Iso.fun = glue
    glue-iso .Iso.inv = uncurry split
    glue-iso .Iso.rightInv (k , p) = glue-split k p
    glue-iso .Iso.leftInv (m , n) = split-glue m n

We can now define the equivalence on positions: Removing the hole from a list of length \( m + 1 + n \) leaves exactly the positions of the two lists surrounding it.

  hole-remove : βˆ€ m n β†’ ([ m + 1 + n ] βˆ– hole m n) ≃ ([ m ] ⊎ [ n ])
  hole-remove zero n =
    (πŸ™ ⊎ [ n ]) βˆ– fzero
      β‰ƒβŸ¨ invEquiv remove-left-equiv ⟩
    (πŸ™ βˆ– β€’) ⊎ [ n ]
      β‰ƒβŸ¨ ⊎-left-≃ remove-β€’ ⟩
    𝟘 ⊎ [ n ]
      β‰ƒβˆŽ
    where
    remove-β€’ : (πŸ™ βˆ– β€’) ≃ 𝟘
    remove-β€’ = isPropβ†’remove-empty-equiv isProp-πŸ™* β€’
  hole-remove (suc m) n =
    (πŸ™ ⊎ [ m + 1 + n ]) βˆ– fsuc (hole m n)
      β‰ƒβŸ¨ invEquiv remove-right-equiv ⟩
    πŸ™ ⊎ ([ m + 1 + n ] βˆ– hole m n)
      β‰ƒβŸ¨ ⊎-right-≃ (hole-remove m n) ⟩
    πŸ™ ⊎ ([ m ] ⊎ [ n ])
      β‰ƒβŸ¨ invEquiv ⊎-assoc-≃ ⟩
    (πŸ™ ⊎ [ m ]) ⊎ [ n ]
      β‰ƒβˆŽ

Thus, lists with a hole correspond exactly to pairs of lists.

  glue-at-hole : (List βŠ— List) ⧟ Listβˆ™
  glue-at-hole .Equiv.shape = glue-equiv
  glue-at-hole .Equiv.pos _ (m , n) = hole-remove m n

  βˆ‚-list-equiv : βˆ‚β€’ List ⧟ (List βŠ— List)
  βˆ‚-list-equiv = forget-isolated-pos ⋆ₑ Equiv.inv glue-at-hole

As a fixpoint

Instead of giving lists directly in terms of length and positions, we can show that they are the (unique) solution to the fixpoint problem \( Y = 1 + X \times Y \). Let's define a two-parameter container \( \mathsf{L} = (S \lhd X, Y) \) and show that \( \mu \mathsf{L} \) is equivalent to \( \mathsf{List} \).

private
  data S : Type where
    nil cons : S

  X : S β†’ Type
  X nil = 𝟘
  X cons = πŸ™

  Y : S β†’ Type
  Y nil = 𝟘
  Y cons = πŸ™

  pattern x = β‚€
  pattern y = ₁

L : Container β„“-zero 𝟚
L .Shape = S
L .Pos x = X
L .Pos y = Y

The construction proceeds by observing that shapes of \( \mu \mathsf{L} \) are trees with at most one branch, hence equivalent to \( β„• \).

μL⧟List : μ L ⧟ List
ΞΌL⧟List = [ depth-equiv ◁≃ path-equiv ]  where

Shapes are trees \( \mathsf{W}(S, Y) \). We compute their depth by induction.

  _ : ΞΌ L .Shape ≑ W S Y
  _ = refl

  depth : W S Y β†’ β„•
  depth = W-rec Ξ» where
    (nil , _) β†’ 0
    (cons , n) β†’ suc (n β€’)

The positions \( Y \) force the tree to branch at most once, consequently there is a unique tree for each depth. This defines the equivalence of shapes.

  depth-equiv : W S Y ≃ β„•
  depth-equiv = isoToEquiv Ξ» where
    .Iso.fun β†’ depth
    .Iso.inv β†’ Nat.elim (sup nil (Ξ» ())) Ξ» n w β†’ sup cons Ξ» _ β†’ w
    .Iso.rightInv β†’ Nat.elim refl Ξ» n β†’ cong suc
    .Iso.leftInv β†’ W-elim Ξ» where
      nil f ind β†’ cong (sup nil) $ funExt Ξ» ()
      cons f ind β†’ cong (sup cons) $ funExt ind

  unique-tree-of-depth : βˆ€ n β†’ βˆƒ![ x ∈ W S Y ] depth x ≑ n
  unique-tree-of-depth = equivIsEquiv depth-equiv .equiv-proof

By induction, it is straightforward to show that there are exactly \( n \) paths into such a tree of depth \( n \). This is the desired equivalence of positions.

  path-equiv : πŸ™ β†’ (x : W S Y) β†’ [ depth x ] ≃ Wα΄° S Y X x
  path-equiv _ = W-elim Ξ» where
    nil f _ β†’ Empty.uninhabEquiv (Ξ» ()) Ξ» where
      (top p) β†’ 𝟘-rec p
      (below p q) β†’ 𝟘-rec p
    cons f ind-≃ β†’
      πŸ™ ⊎ [ depth (f β€’) ]
        β‰ƒβŸ¨ ⊎-right-≃ $ ind-≃ β€’ ⟩
      πŸ™ ⊎ (Wα΄° S Y X (f β€’))
        β‰ƒβŸ¨ ⊎-right-≃ $ invEquiv $ Sigma.Ξ£-contractFst isContr-πŸ™* ⟩
      πŸ™ ⊎ (Ξ£[ p ∈ πŸ™ ] Wα΄° S Y X (f p))
        β‰ƒβŸ¨ Wα΄°-in-equiv _ _ _ cons f ⟩
      Wα΄° S Y X (sup cons f)
        β‰ƒβˆŽ