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) ββ