module StringLab.Data.List.Factor where
Factorsπ
A word is a factor of a word if there merely exists such that
Note that mere existence is required to make this a proposition: there are multiple ways to witness as a factor of a non-empty list.
_β_ : List A β List A β Type _ _β_ {A = A} xs ys = β₯ Ξ£[ us β List A ] Ξ£[ vs β List A ] us ++ xs ++ vs β‘ ys β₯
A word is a left factor of a word denoted if there exists some such that
_βΛ‘_ : List A β List A β Type _ _βΛ‘_ {A = A} xs ys = Ξ£[ us β List A ] xs ++ us β‘ ys
Conversely, a word is a right factor of a word denoted if there exists some such that
_βΚ³_ : List A β List A β Type _ _βΚ³_ {A = A} xs ys = Ξ£[ us β List A ] us ++ xs β‘ ys
A word is a proper left factor of denoted if there exists a non-empty word such that
Likewise, a word is a proper right factor of denoted if there exists a non-empty word such that
_βΛ‘_ : List A β List A β Type _ _βΛ‘_ {A = A} xs ys = Ξ£[ u β A ] Ξ£[ us β List A ] xs ++ (u β· us) β‘ ys _βΚ³_ : List A β List A β Type _ _βΚ³_ {A = A} xs ys = Ξ£[ u β A ] Ξ£[ us β List A ] (u β· us) ++ xs β‘ ys
Left factors are more commonly known as prefixes, and right factors as suffixes. We choose the left/right factor terminology to emphasize the algebraic nature of factorisations.
Convienence functionsπ
We start by defining some nicer names for left factor corresponding to a right factor, and vice versa.
βΛ‘-factor : β {xs ys : List A} β xs βΛ‘ ys β List A βΛ‘-factor = fst βΚ³-factor : β {xs ys : List A} β xs βΚ³ ys β List A βΚ³-factor = fst βΛ‘-dual-βΚ³ : β {xs ys : List A} β (p : xs βΛ‘ ys) β βΛ‘-factor p βΚ³ ys βΛ‘-dual-βΚ³ {xs = xs} (vs , p) = xs , p βΚ³-dual-βΛ‘ : β {xs ys : List A} β (p : xs βΚ³ ys) β βΚ³-factor p βΛ‘ ys βΚ³-dual-βΛ‘ {xs = xs} (vs , p) = xs , p
Note that the corresponding right factor of a proper left factor may not be proper, and vice versa for proper right factors.
βΛ‘-factor : β {xs ys : List A} β xs βΛ‘ ys β List A βΛ‘-factor (u , us , _) = u β· us βΛ‘-dual-βΚ³ : {xs ys : List A} β (p : xs βΛ‘ ys) β βΛ‘-factor p βΚ³ ys βΛ‘-dual-βΚ³ {xs = xs} (u , us , p) = xs , p βΚ³-factor : β {xs ys : List A} β xs βΚ³ ys β List A βΚ³-factor (u , us , _) = u β· us βΚ³-dual-βΛ‘ : {xs ys : List A} β (p : xs βΚ³ ys) β βΚ³-factor p βΛ‘ ys βΚ³-dual-βΛ‘ {xs = xs} (u , us , p) = xs , p
However, the corresponding right/left factors of proper left/right factors are always non-empty
βΛ‘-factor-nonempty : β {xs ys : List A} β (xsβys : xs βΛ‘ ys) β Nonempty (βΛ‘-factor xsβys) βΛ‘-factor-nonempty xsβys = nonempty βΚ³-factor-nonempty : β {xs ys : List A} β (xsβys : xs βΚ³ ys) β Nonempty (βΚ³-factor xsβys) βΚ³-factor-nonempty xsβys = nonempty
This also gives us a method for constructing proper factors.
++-nonempty-βΛ‘ : β (xs ys zs : List A) β Nonempty ys β xs ++ ys β‘ zs β xs βΛ‘ zs ++-nonempty-βΛ‘ xs (y β· ys) zs _ p = y , ys , p ++-nonempty-βΚ³ : β (xs ys zs : List A) β Nonempty xs β xs ++ ys β‘ zs β ys βΚ³ zs ++-nonempty-βΚ³ (x β· xs) ys zs _ p = x , xs , p
The following are also clearly factorisations.
βΛ‘-++-inl : β (xs ys : List A) β xs βΛ‘ xs ++ ys βΛ‘-++-inl xs ys = ys , refl βΛ‘-++-inl : β (xs ys : List A) β β¦ _ : Nonempty ys β¦ β xs βΛ‘ xs ++ ys βΛ‘-++-inl xs (y β· ys) = y , ys , refl βΚ³-++-inr : β (xs ys : List A) β ys βΚ³ xs ++ ys βΚ³-++-inr xs ys = xs , refl βΚ³-++-inr : β (xs ys : List A) β β¦ _ : Nonempty xs β¦ β ys βΚ³ xs ++ ys βΚ³-++-inr (x β· xs) ys = x , xs , refl
We also have corresponding versionns of these lemmas for fused reverse-and-add, though we only include the version we need for the time being.
βΚ³-β-inr : β (xs ys : List A) β xs βΚ³ ys β xs βΚ³-β-inr xs ys = reverse ys , sym (β-exchangel [] ys xs)
Strengthening and weakeningπ
Clearly, proper left/right factors are left/right factors.
βΚ³-weaken : β {xs ys : List A} β xs βΚ³ ys β xs βΚ³ ys βΚ³-weaken (u , us , p) = (u β· us) , p βΛ‘-weaken : β {xs ys : List A} β xs βΛ‘ ys β xs βΛ‘ ys βΛ‘-weaken (u , us , p) = (u β· us) , p
Moreover, a left/right factor of is either a proper factor, or equal to Note that this does not require decidable equality; just check the length of the other list.
βΛ‘-strengthen : β {xs ys : List A} β xs βΛ‘ ys β (xs β‘ ys) β (xs βΛ‘ ys) βΛ‘-strengthen ([] , p) = inl (sym (++-idr _) β p) βΛ‘-strengthen (u β· us , p) = inr (u , us , p) βΚ³-strengthen : β {xs ys : List A} β xs βΚ³ ys β (xs β‘ ys) β (xs βΚ³ ys) βΚ³-strengthen ([] , p) = inl p βΚ³-strengthen (u β· us , p) = inr (u , us , p)
We can also mediate between proper right factors of non-empty lists, and factors of the tails of those lists.
βΚ³-consr : β {xs : List A} {y : A} {ys : List A} β xs βΚ³ ys β xs βΚ³ (y β· ys) βΚ³-consr {y = y} (us , p) = y , us , ap (y β·_) p βΚ³-tailr : β {xs ys : List A} β xs βΚ³ ys β xs βΚ³ tail ys βΚ³-tailr (u , us , p) = us , ap tail p
Dual results hold for left factors and snoc.
βΛ‘-snocr : β {xs : List A} {ys : List A} {y : A} β xs βΛ‘ ys β xs βΛ‘ (ys β·r y) βΛ‘-snocr {xs = xs} {ys = ys} {y = y} (us , p) = head y us , tail (us β·r y) , path where path : xs ++ head y us β· tail (us β·r y) β‘ ys β·r y path = xs ++ head y us β· tail (us β·r y) β‘β¨ ap (xs ++_) (head-tail-β· y us) β©β‘ xs ++ us β·r y β‘Λβ¨ ++-assoc xs us (y β· []) β©β‘Λ (xs ++ us) β·r y β‘β¨ ap (_β·r y) p β©β‘ ys β·r y β βΛ‘-initr : β {xs ys : List A} β xs βΛ‘ ys β xs βΛ‘ init ys βΛ‘-initr {xs = xs} {ys = ys} (u , us , p) = init (u β· us) , path where path : xs ++ init (u β· us) β‘ init ys path = xs ++ init (u β· us) β‘Λβ¨ init-nonempty-++ xs (u β· us) β©β‘Λ init (xs ++ u β· us) β‘β¨ ap init p β©β‘ init ys β
In fact, we can precisely characterise proper left/right factors as left/right factors whose corresponding right/left factor is nonempty.
βΛ‘ββΛ‘-nonempty : β {A : Type β} β (xs ys : List A) β (xs βΛ‘ ys) β (Ξ£[ p β xs βΛ‘ ys ] Nonempty (βΛ‘-factor p)) βΚ³ββΚ³-nonempty : β {A : Type β} β (xs ys : List A) β (xs βΚ³ ys) β (Ξ£[ p β xs βΚ³ ys ] Nonempty (βΚ³-factor p))
This is surprisingly annoying to prove: the easiest way is to chain a
series of equivalences that reassociate quantifiers, and then invoke
nonemptyββ·.
βΛ‘ββΛ‘-nonempty {A = A} xs ys = Ξ£[ u β A ] Ξ£[ us β List A ] xs ++ u β· us β‘ ys ββ¨ Ξ£-assoc β©β Ξ£[ uus β (A Γ List A) ] xs ++ uus .fst β· uus .snd β‘ ys ββ¨ Ξ£-ap (nonemptyββ· eβ»ΒΉ) (Ξ» (u , us) β pathβequiv (lemma u us)) β©β Ξ£ (Ξ£ (List A) Nonempty) (Ξ» (us , _) β xs ++ us β‘ ys) βΛβ¨ Ξ£-assoc β©βΛ Ξ£[ us β List A ] (Nonempty us Γ xs ++ us β‘ ys) ββ¨ Ξ£-ap idβ (Ξ» _ β Γ-swap) β©β Ξ£[ us β List A ] (xs ++ us β‘ ys Γ Nonempty us) ββ¨ Ξ£-assoc β©β Ξ£[ p β xs βΛ‘ ys ] Nonempty (p .fst) ββ where lemma : β u us β _ lemma u us = apβ _β‘_ (apβ (Ξ» u us β xs ++ u β· us) (sym (transport-refl _)) (sym (transport-refl _ β transport-refl _))) refl
The case for right factors is nearly identical and equally as tedious, so we omit the details.
βΚ³ββΚ³-nonempty {A = A} xs ys = Ξ£[ u β A ] Ξ£[ us β List A ] u β· us ++ xs β‘ ys ββ¨ Ξ£-assoc β©β Ξ£[ uus β (A Γ List A) ] uus .fst β· uus .snd ++ xs β‘ ys ββ¨ Ξ£-ap (nonemptyββ· eβ»ΒΉ) (Ξ» (u , us) β pathβequiv (lemma u us)) β©β Ξ£ (Ξ£ (List A) Nonempty) (Ξ» (us , _) β us ++ xs β‘ ys) βΛβ¨ Ξ£-assoc β©βΛ Ξ£[ us β List A ] (Nonempty us Γ us ++ xs β‘ ys) ββ¨ Ξ£-ap idβ (Ξ» _ β Γ-swap) β©β Ξ£[ us β List A ] (us ++ xs β‘ ys Γ Nonempty us) ββ¨ Ξ£-assoc β©β Ξ£[ p β xs βΚ³ ys ] Nonempty (p .fst) ββ where lemma : β u us β _ lemma u us = apβ _β‘_ (apβ (Ξ» u us β u β· us ++ xs) (sym (transport-refl _)) (sym (transport-refl _ β transport-refl _))) refl
Bottom elementsπ
The empty list is a bottom element for all the factorization orders.
βΛ‘-bot : β {xs : List A} β [] βΛ‘ xs βΛ‘-bot {xs = xs} = xs , refl βΛ‘-bot : β {x : A} {xs : List A} β [] βΛ‘ (x β· xs) βΛ‘-bot {x = x} {xs = xs} = x , xs , refl βΚ³-bot : β {xs : List A} β [] βΚ³ xs βΚ³-bot {xs = xs} = xs , ++-idr xs βΚ³-bot : β {x : A} {xs : List A} β [] βΚ³ (x β· xs) βΚ³-bot {x = x} {xs = xs} = x , xs , ++-idr (x β· xs)
There are no proper left or right factors of the empty list.
βΛ‘-strict-bot : β {x : A} {xs : List A} β Β¬ (x β· xs βΛ‘ []) βΛ‘-strict-bot (us , p) = absurd (β·β [] p) βΛ‘-strict-bot : β (xs : List A) β Β¬ (xs βΛ‘ []) βΛ‘-strict-bot xs (u , us , p) = absurd (β·β [] (++-zeror xs (u β· us) p)) βΚ³-strict-bot : β {x : A} {xs : List A} β Β¬ (x β· xs βΚ³ []) βΚ³-strict-bot {x = x} {xs = xs} (us , p) = absurd (β·β [] (++-zeror us (x β· xs) p)) βΚ³-strict-bot : β (xs : List A) β Β¬ (xs βΚ³ []) βΚ³-strict-bot xs (u , us , p) = absurd (β·β [] p)
There are many ways we can repackage this fact: the following list is not exhaustive, and covers all the cases we will need.
empty-not-βΚ³-empty : β {xs ys : List A} β Empty xs β Empty ys β Β¬ (xs βΚ³ ys) empty-not-βΚ³-empty {xs = []} {ys = []} _ _ = βΚ³-strict-bot [] βΚ³-nonempty : β {xs : List A} β Nonempty xs β [] βΚ³ xs βΚ³-nonempty {xs = x β· xs} _ = βΚ³-bot nonempty-βΛ‘ : β {xs ys : List A} β xs βΛ‘ ys β Nonempty ys nonempty-βΛ‘ {ys = []} xsβys = absurd (βΛ‘-strict-bot _ xsβys) nonempty-βΛ‘ {ys = y β· ys} xsβys = nonempty nonempty-βΚ³ : β {xs ys : List A} β xs βΚ³ ys β Nonempty ys nonempty-βΚ³ {ys = []} xsβys = absurd (βΚ³-strict-bot _ xsβys) nonempty-βΚ³ {ys = y β· ys} xsβys = nonempty
Monotonicityπ
If has a nonempty left/right factor then must also be nonempty.
nonempty-βΛ‘-stable : β {xs : List A} {ys : List A} β β¦ _ : Nonempty xs β¦ β xs βΛ‘ ys β Nonempty ys nonempty-βΛ‘-stable {xs = x β· xs} {ys = []} (us , p) = absurd (β·β [] p) nonempty-βΛ‘-stable {xs = x β· xs} {ys = y β· ys} (us , p) = nonempty nonempty-βΚ³-stable : β {xs : List A} {ys : List A} β β¦ _ : Nonempty xs β¦ β xs βΚ³ ys β Nonempty ys nonempty-βΚ³-stable {xs = x β· xs} {ys = []} (us , p) = absurd (β·β [] (++-zeror us (x β· xs) p)) nonempty-βΚ³-stable {xs = x β· xs} {ys = y β· ys} (us , p) = nonempty
Lengths of factorsπ
If is a proper left factor of then the length of is strictly smaller than the length of
βΛ‘-length-< : β {xs ys : List A} β xs βΛ‘ ys β length xs Nat.< length ys βΛ‘-length-< {xs = xs} {ys = ys} (u , us , xs+us=ys) = β€-trans (+-β€l (suc (length xs)) (length us)) $ β€-refl' 1+β£xsβ£+β£usβ£=β£ysβ£ where 1+β£xsβ£+β£usβ£=β£ysβ£ : 1 + length xs + length us β‘ length ys 1+β£xsβ£+β£usβ£=β£ysβ£ = 1 + length xs + length us β‘Λβ¨ +-sucr (length xs) (length us) β©β‘Λ length xs + (1 + length us) β‘β¨β© length xs + length (u β· us) β‘Λβ¨ length-++ xs (u β· us) β©β‘Λ length (xs ++ u β· us) β‘β¨ ap length xs+us=ys β©β‘ length ys β
Extending factorsπ
We can extend left prefixes on the left, and right prefixes on the right.
βΛ‘-++-extendl : β {ws xs ys zs : List A} β ws β‘ xs β ys βΛ‘ zs β (ws ++ ys) βΛ‘ (xs ++ zs) βΛ‘-++-extendl {ws = ws} {ys = ys} p (us , q) = us , ++-assoc ws ys us β apβ _++_ p q βΛ‘-++-extendl : β {ws xs ys zs : List A} β ws β‘ xs β ys βΛ‘ zs β (ws ++ ys) βΛ‘ (xs ++ zs) βΛ‘-++-extendl {ws = ws} {ys = ys} p (u , us , q) = u , us , ++-assoc ws ys (u β· us) β apβ _++_ p q βΚ³-++-extendr : β {ws xs ys zs : List A} β ws βΚ³ xs β ys β‘ zs β (ws ++ ys) βΚ³ (xs ++ zs) βΚ³-++-extendr {ws = ws} {ys = ys} (us , p) q = us , sym (++-assoc us ws ys) β apβ _++_ p q βΚ³-++-extendr : β {ws xs ys zs : List A} β ws βΚ³ xs β ys β‘ zs β (ws ++ ys) βΚ³ (xs ++ zs) βΚ³-++-extendr {ws = ws} {ys = ys} (u , us , p) q = u , us , sym (++-assoc (u β· us) ws ys) β apβ _++_ p q
As corollaries, we get can extend left/right prefixes with a single element on the left/right, resp.
βΛ‘-β·-extendl : β {x y : A} {xs ys : List A} β x β‘ y β xs βΛ‘ ys β (x β· xs) βΛ‘ (y β· ys) βΛ‘-β·-extendl p q = βΛ‘-++-extendl (ap (_β· []) p) q βΛ‘-β·-extendl : β {x y : A} {xs ys : List A} β x β‘ y β xs βΛ‘ ys β (x β· xs) βΛ‘ (y β· ys) βΛ‘-β·-extendl p q = βΛ‘-++-extendl (ap (_β· []) p) q βΚ³-β·r-extendr : β {x y : A} {xs ys : List A} β xs βΚ³ ys β x β‘ y β (xs β·r x) βΚ³ (ys β·r y) βΚ³-β·r-extendr p q = βΚ³-++-extendr p (ap (_β· []) q) βΚ³-β·r-extendr : β {x y : A} {xs ys : List A} β xs βΚ³ ys β x β‘ y β (xs β·r x) βΚ³ (ys β·r y) βΚ³-β·r-extendr p q = βΚ³-++-extendr p (ap (_β· []) q)
We also have extension lemmata for fused reverse-and-concatenate.
βΚ³-β-extendr : β {ws xs ys zs : List A} β ws βΛ‘ xs β ys β‘ zs β (ws β ys) βΚ³ (xs β zs) βΚ³-β-extendr {ws = ws} {xs = xs} {ys = ys} {zs = zs} (vs , p) ys=zs = reverse vs , β-exchanger vs [] (ws β ys) β β-assocl vs ws ys β apβ (_β_) p ys=zs
Inversion lemmasπ
Next, we prove a battery of rather tedious inversion lemmas. These sorts of lemmas are (understandably) often omitted in informal accounts of the subject, but we are being completely formal, so a bit of elbow grease is required. Luckily, none of them are particularly hard, so we shall gloss over the proofs.
We begin by charaterising left factors of non-empty lists. In particular, if is a nonempty factor of a nonempty list then their first elements must be equal, and their tails must be factors.
βΛ‘-head : {xs ys : List A} β β¦ _ : Nonempty xs β¦ β β¦ _ : Nonempty ys β¦ β xs βΛ‘ ys β headβΊ xs β‘ headβΊ ys βΛ‘-head {xs = x β· xs} {ys = y β· ys} (us , p) = β·-head-inj p βΛ‘-tail : {xs ys : List A} β xs βΛ‘ ys β tail xs βΛ‘ tail ys βΛ‘-tail {xs = []} {ys = ys} _ = βΛ‘-bot βΛ‘-tail {xs = x β· xs} {ys = []} (us , p) = absurd (β·β [] p) βΛ‘-tail {xs = x β· xs} {ys = y β· ys} (us , p) = us , β·-tail-inj p βΛ‘-head : β {xs ys : List A} β β¦ _ : Nonempty xs β¦ β β¦ _ : Nonempty ys β¦ β xs βΛ‘ ys β headβΊ xs β‘ headβΊ ys βΛ‘-head {xs = x β· xs} {ys = y β· ys} (u , us , p) = β·-head-inj p βΛ‘-tail : β {xs ys : List A} β β¦ _ : Nonempty xs β¦ β β¦ _ : Nonempty ys β¦ β xs βΛ‘ ys β tail xs βΛ‘ tail ys βΛ‘-tail {xs = x β· xs} {ys = y β· ys} (u , us , p) = u , us , β·-tail-inj p
We also have analogous lemmas for right factors and init/last.
βΚ³-last : β {xs ys : List A} β β¦ _ : Nonempty xs β¦ β β¦ _ : Nonempty ys β¦ β xs βΚ³ ys β lastβΊ xs β‘ lastβΊ ys βΚ³-last {xs = x β· xs} {ys = y β· ys} (us , p) = last xs x β‘Λβ¨ last-nonempty-++ us (x β· xs) x x β©β‘Λ last β us ++ x β· xs β x β‘β¨ ap! p β©β‘ last (y β· ys) x β‘β¨β© last ys y β βΚ³-init : β {xs ys : List A} β xs βΚ³ ys β init xs βΚ³ init ys βΚ³-init {xs = []} {ys = ys} xsβys = βΚ³-bot βΚ³-init {xs = x β· xs} {ys = []} xsβys = absurd (βΚ³-strict-bot xsβys) βΚ³-init {xs = x β· xs} {ys = y β· ys} (us , p) = us , (sym (init-nonempty-++ us (x β· xs)) β ap init p) βΚ³-last : β {xs ys : List A} β β¦ _ : Nonempty xs β¦ β β¦ _ : Nonempty ys β¦ β xs βΚ³ ys β lastβΊ xs β‘ lastβΊ ys βΚ³-last (u , us , p) = βΚ³-last (u β· us , p) βΚ³-init : β {xs ys : List A} β β¦ Nonempty xs β¦ β β¦ Nonempty ys β¦ β xs βΚ³ ys β init xs βΚ³ init ys βΚ³-init {xs = x β· xs} {ys = y β· ys} (u , us , p) = u , us , sym (init-nonempty-++ (u β· us) (x β· xs)) β ap init p
Moreover, if is a (proper) right factor of then the tail of is a (proper) right factor of the tail of
βΚ³-tail : β {xs ys : List A} β xs βΚ³ ys β tail xs βΚ³ tail ys βΚ³-β·-tail : β {xs ys : List A} β β¦ _ : Nonempty xs β¦ β β¦ _ : Nonempty ys β¦ β xs βΚ³ ys β tail xs βΚ³ tail ys
The proof is easy, but tedious. Dedicated readers can click βread moreβ to see the details.
βΚ³-tail {xs = []} {ys = ys} xsβys = βΚ³-bot βΚ³-tail {xs = x β· xs} {ys = []} xsβys = absurd (βΚ³-strict-bot xsβys) βΚ³-tail {xs = x β· xs} {ys = y β· ys} (us , p) = tail (us β·r x) , us+xs=ys where us+xs=ys : tail (us β·r x) ++ xs β‘ ys us+xs=ys = tail (us β·r x) ++ xs β‘Λβ¨ tail-nonempty-++ (us β·r x) xs β©β‘Λ tail (us β·r x ++ xs) β‘β¨ ap tail (++-assoc us (x β· []) xs) β©β‘ tail (us ++ x β· xs) β‘β¨ ap tail p β©β‘ ys β βΚ³-β·-tail {xs = x β· xs} {ys = y β· ys} (u , us , p) = head x us , tail (us β·r x) , us+xs=ys where us+xs=ys : head x us β· tail (us β·r x) ++ xs β‘ ys us+xs=ys = head x us β· tail (us β·r x) ++ xs β‘β¨ ap (_++ xs) (head-tail-β· x us) β©β‘ us β·r x ++ xs β‘β¨ ++-assoc us (x β· []) xs β©β‘ us ++ x β· xs β‘β¨ β·-tail-inj p β©β‘ ys β
We can repackage some of these inversion lemmas in forms that are more ergonomic in some situations.
βΚ³-β·-inversion : β {us : List β A β} {x : β A β} {xs : List β A β} β us βΚ³ x β· xs β (us β‘ x β· xs) β us βΚ³ xs βΚ³-β·-inversion ([] , p) = inl p βΚ³-β·-inversion (v β· vs , p) = inr (vs , β·-tail-inj p) βΚ³-β·-shrinkl : β {u : β A β} {us : List β A β} {xs : List β A β} β u β· us βΚ³ xs β us βΚ³ xs βΚ³-β·-shrinkl {u = u} {us = us} (v , vs , p) = v , vs β·r u , ap (v β·_) (++-assoc vs (u β· []) us) β p βΚ³-β·-extendr : β {us : List β A β} {x : β A β} {xs : List β A β} β us βΚ³ xs β us βΚ³ (x β· xs) βΚ³-β·-extendr {x = x} (vs , p) = (x β· vs , ap (x β·_) p)
Factorisations as ordersπ
The left/right factorisation relations are reflexive.
βΛ‘-refl' : β {xs ys : List A} β xs β‘ ys β xs βΛ‘ ys βΛ‘-refl' p = [] , ++-idr _ β p βΛ‘-refl : β {xs : List A} β xs βΛ‘ xs βΛ‘-refl {xs = xs} = [] , ++-idr _ βΚ³-refl' : β {xs ys : List A} β xs β‘ ys β xs βΚ³ ys βΚ³-refl' p = [] , p βΚ³-refl : β {xs : List A} β xs βΚ³ xs βΚ³-refl {xs = xs} = [] , refl
Conversely, the proper factor relations are irreflexive.
βΛ‘-irrefl' : β {xs ys : List A} β xs βΛ‘ ys β xs β ys βΚ³-irrefl' : β {xs ys : List A} β xs βΚ³ ys β xs β ys
This follows from some easy algebra: if they were reflexive, β then there would be some nonempty such that had a fixpoint.
βΛ‘-irrefl' {ys = ys} (u , us , p) xs=ys = ++-no-fixl _ (u β· us) (ap (_++ u β· us) (sym xs=ys) β p) βΚ³-irrefl' (u , us , p) xs=ys = ++-no-fixr (u β· us) _ (ap (u β· us ++_) (sym xs=ys) β p)
The more general form of irreflexivity can be annoying to use, so we repackage the result into a friendlier form.
βΛ‘-irrefl : β {xs : List A} β Β¬ (xs βΛ‘ xs) βΛ‘-irrefl xsβxs = βΛ‘-irrefl' xsβxs refl βΚ³-irrefl : β {xs : List A} β Β¬ (xs βΚ³ xs) βΚ³-irrefl xsβxs = βΚ³-irrefl' xsβxs refl
The (proper) factorisation relations are not only (ir)reflexive, they are transitive! This follows from some easy algebra in all cases.
βΛ‘-trans : β {xs ys zs : List A} β xs βΛ‘ ys β ys βΛ‘ zs β xs βΛ‘ zs βΛ‘-trans (us , p) (vs , q) = us ++ vs , sym (++-assoc _ us vs) β ap (_++ vs) p β q βΚ³-trans : β {xs ys zs : List A} β xs βΚ³ ys β ys βΚ³ zs β xs βΚ³ zs βΚ³-trans (us , p) (vs , q) = vs ++ us , ++-assoc vs us _ β ap (vs ++_) p β q βΛ‘-trans : β {xs ys zs : List A} β xs βΛ‘ ys β ys βΛ‘ zs β xs βΛ‘ zs βΛ‘-trans (u , us , p) (v , vs , q) = u , (us ++ v β· vs) , sym (++-assoc _ (u β· us) (v β· vs)) β ap (_++ v β· vs) p β q βΚ³-trans : β {xs ys zs : List A} β xs βΚ³ ys β ys βΚ³ zs β xs βΚ³ zs βΚ³-trans (u , us , p) (v , vs , q) = v , (vs ++ u β· us) , ++-assoc (v β· vs) (u β· us) _ β ap (v β· vs ++_) p β q
We also have joint transitivity of the proper and non-proper factorisation relations.
βΛ‘-βΛ‘-trans : β {xs ys zs : List A} β xs βΛ‘ ys β ys βΛ‘ zs β xs βΛ‘ zs βΛ‘-βΛ‘-trans : β {xs ys zs : List A} β xs βΛ‘ ys β ys βΛ‘ zs β xs βΛ‘ zs βΚ³-βΚ³-trans : β {xs ys zs : List A} β xs βΚ³ ys β ys βΚ³ zs β xs βΚ³ zs βΚ³-βΚ³-trans : β {xs ys zs : List A} β xs βΚ³ ys β ys βΚ³ zs β xs βΚ³ zs
These all follow from our previous transitivity lemmas.
βΛ‘-βΛ‘-trans {xs = xs} {ys = ys} {zs = zs} xsβys ysβzs = Equiv.from (βΛ‘ββΛ‘-nonempty xs zs) $ βΛ‘-trans (βΛ‘-weaken xsβys) ysβzs , auto βΛ‘-βΛ‘-trans {xs = xs} {ys = ys} {zs = zs} xsβys ysβzs = Equiv.from (βΛ‘ββΛ‘-nonempty xs zs) $ βΛ‘-trans xsβys (βΛ‘-weaken ysβzs) , auto βΚ³-βΚ³-trans {xs = xs} {ys = ys} {zs = zs} xsβys ysβzs = Equiv.from (βΚ³ββΚ³-nonempty xs zs) $ βΚ³-trans (βΚ³-weaken xsβys) ysβzs , auto βΚ³-βΚ³-trans {xs = xs} {ys = ys} {zs = zs} xsβys ysβzs = Equiv.from (βΚ³ββΚ³-nonempty xs zs) $ βΚ³-trans xsβys (βΚ³-weaken ysβzs) , auto
The proper left/right factor relations are jointly asymmetric with both non-proper factorisation relations.
βΛ‘-βΛ‘-asym : β {xs ys : List A} β xs βΛ‘ ys β ys βΛ‘ xs β β₯ βΛ‘-βΚ³-asym : β {xs ys : List A} β xs βΛ‘ ys β ys βΚ³ xs β β₯ βΚ³-βΛ‘-asym : β {xs ys : List A} β xs βΚ³ ys β ys βΛ‘ xs β β₯ βΚ³-βΚ³-asym : β {xs ys : List A} β xs βΚ³ ys β ys βΚ³ xs β β₯
All these follow from fixpoint arguments.
βΚ³-βΛ‘-asym {ys = ys} (u , us , p) (vs , q) = ++-no-fix (u β· us) ys vs (inl nonempty) (ap (u β· us ++_) q β p) βΛ‘-βΚ³-asym {ys = ys} (u , us , p) (vs , q) = ++-no-fix vs ys (u β· us) (inr nonempty) (sym (++-assoc vs ys (u β· us)) β ap (_++ u β· us) q β p) βΚ³-βΚ³-asym {xs = xs} {ys = ys} (u , us , p) (vs , q) = ++-no-fixr (u β· us ++ vs) ys $ (u β· us ++ vs) ++ ys β‘β¨ ++-assoc (u β· us) vs ys β©β‘ u β· us ++ vs ++ ys β‘β¨ ap (u β· us ++_) q β©β‘ u β· us ++ xs β‘β¨ p β©β‘ ys β βΛ‘-βΛ‘-asym {xs = xs} {ys = ys} (u , us , p) (vs , q) = ++-no-fixl xs (u β· us ++ vs) $ xs ++ u β· us ++ vs β‘Λβ¨ ++-assoc xs (u β· us) vs β©β‘Λ (xs ++ u β· us) ++ vs β‘β¨ ap (_++ vs) p β©β‘ ys ++ vs β‘β¨ q β©β‘ xs β
Non-joint asymmetry follows immediately from weakening
βΛ‘-asym : β {xs ys : List A} β xs βΛ‘ ys β ys βΛ‘ xs β β₯ βΛ‘-asym xsβys ysβxs = βΛ‘-βΛ‘-asym xsβys (βΛ‘-weaken ysβxs) βΚ³-asym : β {xs ys : List A} β xs βΚ³ ys β ys βΚ³ xs β β₯ βΚ³-asym xsβys ysβxs = βΚ³-βΚ³-asym xsβys (βΚ³-weaken ysβxs)
Leviβs lemmaπ
The next obvious step is to prove antisymmetry of the factorisation relations. This is slightly tricker than the other cases, so we will take a slight detour to prove Leviβs lemma (Levi 1944): if two words then there is some list that characterises their overlap. In more succinct terms, the free monoid is equidivisible.
++-equidiv : β {β} {A : Type β} β (as bs xs ys : List A) β as ++ bs β‘ xs ++ ys β Ξ£[ us β List A ] ((as β‘ xs ++ us Γ us ++ bs β‘ ys) β (as ++ us β‘ xs Γ bs β‘ us ++ ys))
The proof is somewhat obvious, but contains algorithmic content. We proceed by induction down and when one of them is empty, we simply returun the other list.
++-equidiv [] bs xs ys as+bs=xs+ys = xs , inr (refl , as+bs=xs+ys) ++-equidiv (a β· as) bs [] ys as+bs=xs+ys = a β· as , inl (refl , as+bs=xs+ys)
If the are both non-empty, we just recurse.
++-equidiv (a β· as) bs (x β· xs) ys as+bs=xs+ys with ++-equidiv as bs xs ys (β·-tail-inj as+bs=xs+ys) ... | us , inl (as=xs+us , us+bs=ys) = us , inl (apβ _β·_ (β·-head-inj as+bs=xs+ys) as=xs+us , us+bs=ys) ... | us , inr (as+us=xs , bs=us+ys) = us , (inr (apβ _β·_ (β·-head-inj as+bs=xs+ys) as+us=xs , bs=us+ys))
Leviβs lemma has some extremely useful corollaries. First, observe that if and are both left/right factors of some common word then either is a proper left/right factor of is a proper left/right of or
βΛ‘-equidiv : β {xs ys zs : List A} β xs βΛ‘ zs β ys βΛ‘ zs β Tri _βΛ‘_ xs ys βΚ³-equidiv : β {xs ys zs : List A} β xs βΚ³ zs β ys βΚ³ zs β Tri _βΚ³_ xs ys
The argument is quite elegant: by definition, for some We then invoke Leviβs lemma to find their overlap: if the overlap is empty, then we immediately know that Moreover, we can deduce if is a proper left factor of or vice-versa by the direction the overlap extends in!
βΛ‘-equidiv {xs = xs} {ys = ys} {zs = zs} (us , p) (vs , q) with ++-equidiv xs us ys vs (p β sym q) ... | [] , inl (xs=ys+[] , _) = eq (flip βΛ‘-irrefl' xs=ys) xs=ys (flip βΛ‘-irrefl' (sym xs=ys)) where xs=ys : xs β‘ ys xs=ys = xs=ys+[] β ++-idr ys ... | [] , inr ([]+xs=ys , _) = eq (flip βΛ‘-irrefl' xs=ys) xs=ys (flip βΛ‘-irrefl' (sym xs=ys)) where xs=ys : xs β‘ ys xs=ys = sym (++-idr xs) β []+xs=ys ... | w β· ws , inl (xs=ys+ws , _) = gt (βΛ‘-asym ysβxs) (βΛ‘-irrefl' ysβxs β sym) ysβxs where ysβxs : ys βΛ‘ xs ysβxs = w , ws , sym xs=ys+ws ... | w β· ws , inr (xs+ws=ys , _) = lt xsβys (βΛ‘-irrefl' xsβys) (βΛ‘-asym xsβys) where xsβys : xs βΛ‘ ys xsβys = w , ws , xs+ws=ys
The right case follows the same line of argument, so we omit the details.
βΚ³-equidiv {xs = xs} {ys = ys} {zs = zs} (us , p) (vs , q) with ++-equidiv us xs vs ys (p β sym q) ... | [] , inl (_ , xs=ys) = eq (flip βΚ³-irrefl' xs=ys) xs=ys (flip βΚ³-irrefl' (sym xs=ys)) ... | [] , inr (_ , xs=ys) = eq (flip βΚ³-irrefl' xs=ys) xs=ys (flip βΚ³-irrefl' (sym xs=ys)) ... | w β· ws , inl (_ , ws+xs=ys) = lt xsβys (βΚ³-irrefl' xsβys) (βΚ³-asym xsβys) where xsβys : xs βΚ³ ys xsβys = w , ws , ws+xs=ys ... | w β· ws , inr (_ , xs=ws+ys) = gt (βΚ³-asym ysβxs) (βΚ³-irrefl' ysβxs β sym) ysβxs where ysβxs : ys βΚ³ xs ysβxs = w , ws , sym xs=ws+ys
We can whittle Leviβs lemma down to an even finer point: if is a proper left/right factor of then is either:
- A proper left/right factor of
- Equal to
- Properly left/right factored by and the corresponding right/left factor is a proper left/right factor of
βΛ‘-split-++ : β {A : Type β} (xs ys zs : List A) β xs βΛ‘ ys ++ zs β (xs βΛ‘ ys) β (xs β‘ ys) β (Ξ£[ ysβxs β ys βΛ‘ xs ] βΛ‘-factor ysβxs βΛ‘ zs) βΚ³-split-++ : β {A : Type β} (xs ys zs : List A) β xs βΚ³ ys ++ zs β (xs βΚ³ zs) β (xs β‘ zs) β (Ξ£[ zsβxs β zs βΚ³ xs ] βΚ³-factor zsβxs βΚ³ ys)
We shall present the proof for right factors. By definition, if is a proper left factor of then there is some nonempty such that Once we apply Leviβs lemma, the rest of the proof essentially becomes definition unfolding.
βΚ³-split-++ xs ys zs (u , us , us+xs=ys+zs) with ++-equidiv (u β· us) xs ys zs us+xs=ys+zs ... | [] , inl (_ , xs=zs) = inr (inl xs=zs) ... | [] , inr (_ , xs=zs) = inr (inl xs=zs) ... | w β· ws , inl (_ , ws+xs=zs) = inl (w , ws , ws+xs=zs) ... | w β· ws , inr (us+ws=ys , xs=ws+zs) = inr (inr ((w , ws , sym xs=ws+zs) , u , us , us+ws=ys))
The left factor case is equivalent, though marginally more tedious.
βΛ‘-split-++ xs ys zs (u , us , xs+us=ys+zs) with ++-equidiv xs (u β· us) ys zs xs+us=ys+zs ... | [] , inl (xs=ys , _) = inr (inl (xs=ys β ++-idr ys)) ... | [] , inr (xs=ys , _) = inr (inl (sym (++-idr xs) β xs=ys)) ... | w β· ws , inl (xs=ys+ws , ws+us=zs) = inr (inr ((w , ws , sym xs=ys+ws) , u , us , ws+us=zs)) ... | w β· ws , inr (xs+ws=ys , _) = inl (w , ws , xs+ws=ys)
Asymmetryπ
Now that we have Leviβs lemma and its corollaries, antisymmetry is easy.
βΛ‘-antisym : β {xs ys : List A} β xs βΛ‘ ys β ys βΛ‘ xs β xs β‘ ys βΚ³-antisym : β {xs ys : List A} β xs βΚ³ ys β ys βΚ³ xs β xs β‘ ys
Suppose that and are left/right factors of one another. In particular, this means that and are both factors of By equidivisibility, we have that or one of or is a proper factor of the other. Joint asymmetry rules out those two cases, which lets us deduce that
βΛ‘-antisym {xs = xs} {ys = ys} xsβys ysβxs with βΛ‘-equidiv xsβys βΛ‘-refl ... | lt xsβys _ _ = absurd (βΛ‘-βΛ‘-asym xsβys ysβxs) ... | eq _ xs=ys _ = xs=ys ... | gt _ _ ysβxs = absurd (βΛ‘-βΛ‘-asym ysβxs xsβys) βΚ³-antisym {xs = xs} {ys = ys} xsβys ysβxs with βΚ³-equidiv xsβys βΚ³-refl ... | lt xsβys _ _ = absurd (βΚ³-βΚ³-asym xsβys ysβxs) ... | eq _ xs=ys _ = xs=ys ... | gt _ _ ysβxs = absurd (βΚ³-βΚ³-asym ysβxs xsβys)
Uniqueness of left and right factorsπ
Note that we do not require mere existence in the definition of left/right factor. This is because there is only one such that witnesses a list as a left/right factor!
βΛ‘-unique : β {xs ys : List A} β (p q : xs βΛ‘ ys) β βΛ‘-factor p β‘ βΛ‘-factor q βΚ³-unique : β {xs ys : List A} β (p q : xs βΚ³ ys) β βΚ³-factor p β‘ βΚ³-factor q
Like many things, these are essentially restatements of Leviβs lemma. We shall focus our attention on the left-factor case. Suppose that If we apply Leviβs lemma to this equation, we can immediately see that the only possible outcome is that any other case results in a fixpoint of concatenation.
βΛ‘-unique {xs = xs} {ys = ys} (us , p) (vs , q) with ++-equidiv xs us xs vs (p β sym q) ... | [] , (inl (_ , us=vs)) = us=vs ... | [] , (inr (_ , us=vs)) = us=vs ... | w β· ws , inl (xs=xs+ws , _) = absurd (++-no-fixl xs (w β· ws) (sym xs=xs+ws)) ... | w β· ws , inr (xs+ws=xs , _) = absurd (++-no-fixl xs (w β· ws) (xs+ws=xs))
A dual argument works for right factors.
βΚ³-unique {xs = xs} {ys = ys} (us , p) (vs , q) with ++-equidiv us xs vs xs (p β sym q) ... | [] , (inl (us=vs , _)) = us=vs β ++-idr vs ... | [] , (inr (us=vs , _)) = sym (++-idr us) β us=vs ... | w β· ws , inl (_ , ws+xs=xs) = absurd (++-no-fixr (w β· ws) xs ws+xs=xs) ... | w β· ws , inr (_ , xs=ws+xs) = absurd (++-no-fixr (w β· ws) xs (sym xs=ws+xs))
If
is a set, then we can prove that _βΛ‘_ and _βΚ³_ are both
propositions.
βΛ‘-is-prop : β {xs ys : List A} β is-set A β is-prop (xs βΛ‘ ys) βΛ‘-is-prop A-set p q = Ξ£-prop-path (Ξ» _ β ListPath.List-is-hlevel zero A-set _ _) (βΛ‘-unique p q) βΚ³-is-prop : β {xs ys : List A} β is-set A β is-prop (xs βΚ³ ys) βΚ³-is-prop A-set p q = Ξ£-prop-path (Ξ» _ β ListPath.List-is-hlevel zero A-set _ _) (βΚ³-unique p q)
Atomsπ
Recall that an atomic element in a monoid is one that cannot be written as a product of two non-invertible elements. When specialized to the free monoid, this precisely describes singleton lists.
We have a handful of useful results detailing factors of atomic elements, but they are all repackaged forms of the same idea: namely, that the only factors of a singleton list are the empty list and itself.
βΚ³-atom : β {xs : List A} {y : A} β xs βΚ³ y β· [] β Empty xs β xs β‘ y β· [] βΚ³-atom {xs = []} {y = y} xsβy = inl empty βΚ³-atom {xs = x β· []} {y = y} xsβy = inr (ap (_β· []) (βΚ³-last xsβy)) βΚ³-atom {xs = x β· x' β· xs} {y = y} xsβy = absurd (βΚ³-strict-bot (βΚ³-init xsβy)) βΚ³-atom : β {xs : List A} {y : A} β xs βΚ³ y β· [] β Empty xs βΚ³-atom {xs = []} {y = y} p = empty βΚ³-atom {xs = x β· xs} {y = y} p = absurd (βΚ³-strict-bot (init (x β· xs)) (βΚ³-init p)) nonempty-Β¬βΚ³-atom : β {xs : List A} {y : A} β Nonempty xs β Β¬ (xs βΚ³ y β· []) nonempty-Β¬βΚ³-atom ne xsβy = Equiv.to emptyβΒ¬nonempty (βΚ³-atom xsβy) ne
We also take the time to observe that the atom last xs
of a non-empty list is a factor of x β· xs.
last-nonempty-βΚ³ : β (x : A) (xs : List A) β β¦ _ : Nonempty xs β¦ β lastβΊ xs β· [] βΚ³ x β· xs last-nonempty-βΚ³ x (x' β· xs) = x , init (x' β· xs) , ap (x β·_) (init-last-β·r xs x')
Relating left and right factorsπ
A word is a right factor of if and only if the reverse of is a left factor of the reverse of
βΚ³βreverse-βΛ‘ : β (xs ys : List A) β (xs βΚ³ ys) β (reverse xs βΛ‘ reverse ys)
The proof is essentially βreverse is an anti-isomorphismβ.
βΚ³βreverse-βΛ‘ xs ys = Ξ£-ap reverse-β Ξ» us β us ++ xs β‘ ys ββ¨ ap reverse , equivβcancellable reverse-is-equiv β©β reverse (us ++ xs) β‘ reverse ys ββ¨ β-pre-equiv (sym (reverse-++ us xs)) β©β reverse xs ++ reverse us β‘ reverse ys ββ
We can extend this result to proper factors by recalling that proper factors are precisely factors whose other half is non-empty.
βΚ³βreverse-βΛ‘ : β (xs ys : List A) β (xs βΚ³ ys) β (reverse xs βΛ‘ reverse ys) βΚ³βreverse-βΛ‘ xs ys = xs βΚ³ ys ββ¨ βΚ³ββΚ³-nonempty xs ys β©β (Ξ£[ p β xs βΚ³ ys ] Nonempty (p .fst)) ββ¨ Ξ£-ap (βΚ³βreverse-βΛ‘ xs ys) (Ξ» xsβys β reverse-nonempty (xsβys .fst) eβ»ΒΉ) β©β (Ξ£[ p β reverse xs βΛ‘ reverse ys ] Nonempty (p .fst)) βΛβ¨ βΛ‘ββΛ‘-nonempty (reverse xs) (reverse ys) β©βΛ reverse xs βΛ‘ reverse ys ββ
A similar argument lets us deduce that left factors are the same as reversed right factors.
βΛ‘βreverse-βΚ³ : β (xs ys : List A) β (xs βΛ‘ ys) β (reverse xs βΚ³ reverse ys) βΛ‘βreverse-βΚ³ xs ys = Ξ£-ap reverse-β Ξ» us β xs ++ us β‘ ys ββ¨ ap reverse , equivβcancellable reverse-is-equiv β©β reverse (xs ++ us) β‘ reverse ys ββ¨ β-pre-equiv (sym (reverse-++ xs us)) β©β reverse us ++ reverse xs β‘ reverse ys ββ
Deciding if a list is a factorπ
If has decidable equality, then we have an easy, efficient algorithm for checking if lists are left factors of one another: simply start checking from the head of the list.
instance Dec-βΛ‘ : β {xs ys : List A} β β¦ _ : Discrete A β¦ β Dec (xs βΛ‘ ys) Dec-βΛ‘ {xs = []} {ys = ys} = yes (ys , refl) Dec-βΛ‘ {xs = x β· xs} {ys = []} = no (β·β [] β snd) Dec-βΛ‘ {xs = x β· xs} {ys = y β· ys} with x β‘? y ... | yes x=y = invmap (Ξ£-mapβ (apβ _β·_ x=y)) (Ξ£-mapβ β·-tail-inj) (holds? (xs βΛ‘ ys)) ... | no Β¬x=y = no (Β¬x=y β β·-head-inj β snd)
Deciding if a list is a right factor is a bit tricker. We are using linked lists as our main datastructure of choice, so they have an inherent leftward bias. There isnβt a good choice here; any solution that tries to use lengths will also end up eating a cost, and accessing the last element is also Therefore, the best option is to reverse the lists, and check if it is a right factor.
Dec-βΚ³ : β {xs ys : List A} β β¦ _ : Discrete A β¦ β Dec (xs βΚ³ ys) Dec-βΚ³ {xs = xs} {ys = ys} = EquivβDec (βΚ³βreverse-βΛ‘ xs ys) (holds? (reverse xs βΛ‘ reverse ys))
Well-foundednessπ
Both the proper left and proper right factor relations are well-founded. This is a critical fact for the correctness of many algorithms, as it lets us prove that the actually terminate.
In a surprising role-reversal, the proof for right factors is easier! This ends up boiling down to the fact that we need make calls on increasingly smaller tails of lists, which lines up with the natural direction of structural induction over lists. From an algorithmic perspective, this is also the preferable iteration order: we donβt need to traverse the entire list to start working, which means that any algorithms that use right-factor induction are naturally online.
βΚ³-wf : Wf {A = List A} _βΚ³_ βΚ³-wf xs = go xs xs βΚ³-refl module βΚ³-wf where go : (xs ys : List A) β .(ys βΚ³ xs) β Acc _βΚ³_ ys go xs [] p = acc (Ξ» zs zsβ[] β absurd (βΚ³-strict-bot zs zsβ[])) go [] (y β· ys) p = absurd (βΚ³-strict-bot p) go (x β· xs) (y β· ys) p = acc Ξ» zs zsβyβ·ys β go xs zs (βΚ³-tailr (βΚ³-βΚ³-trans zsβyβ·ys p))
Left factors are much more troublesome, and require us to reverse a list. The fundamental issue here is that we need to shrink the list from starting from the final element, which just does not line up with structural recursion over lists. Reversing a list fixes this, but does make the proof much clunkier.
βΛ‘-wf : Wf {A = List A} _βΛ‘_ βΛ‘-wf xs = go (reverse xs) xs (βΛ‘-refl' (sym (reverse-reverse xs))) module βΛΛ‘-wf where go : (xs ys : List A) β .(ys βΛ‘ reverse xs) β Acc _βΛ‘_ ys go xs [] p = acc Ξ» zs zsβ[] β absurd (βΛ‘-strict-bot zs zsβ[]) go [] (y β· ys) p = absurd (βΛ‘-strict-bot p) go (x β· xs) (y β· ys) p = acc Ξ» zs zsβyβ·ys β go xs zs $α΅’ βΛ‘-trans (βΛ‘-initr (βΛ‘-βΛ‘-trans zsβyβ·ys p)) $ βΛ‘-refl' (init-nonempty-β xs (x β· []))
Fixpointsπ
We can repackage our prior fixpoint lemmas as statements about factors; this is essentially a restatement of irreflexivity.
βΚ³-no-fixl : β (xs ys : List A) β Nonempty ys β Β¬ (xs ++ ys βΚ³ xs) βΚ³-no-fixl xs ys ne (vs , p) = ++-no-fix vs xs ys (inr ne) p βΚ³-no-fixr : β (xs ys : List A) β β¦ Nonempty xs β¦ β Β¬ (xs ++ ys βΚ³ ys) βΚ³-no-fixr xs ys (vs , p) = ++-no-fixr (vs ++ xs) ys β¦ ++-nonemptyr vs xs auto β¦ (++-assoc vs xs ys β p)
Factors of concatenationsπ
If is a proper right factor of and then is a proper right factor of
βΚ³-++-restrictl : β {ws xs : List A} β (ys zs : List A) β length ys β‘ length zs β (ws ++ ys) βΚ³ (xs ++ zs) β ws βΚ³ xs
The proof is a bit of straightforward algebra that hinges on the
following observation from earlier: if
and
then
Once we have this, the proof is reduced to shuffling around a take.
βΚ³-++-restrictl {ws = ws} {xs = xs} ys zs ys-zs-same-len (u , us , p) = ++-nonempty-βΚ³ (u β· us) ws xs nonempty $ u β· us ++ ws β‘Λβ¨ take-all (length (u β· us ++ ws)) (u β· us ++ ws) β€-refl β©β‘Λ take (length (u β· us ++ ws)) (u β· us ++ ws) β‘Λβ¨ take-++l (length (u β· us ++ ws)) (u β· us ++ ws) ys β€-refl β©β‘Λ take β length (u β· us ++ ws) β ((u β· us ++ ws) ++ ys) β‘β¨ ap! us+ws-xs-same-len β©β‘ take (length xs) ((u β· us ++ ws) ++ ys) β‘β¨ ap (take (length xs)) (++-assoc (u β· us) ws ys) β©β‘ take (length xs) (u β· us ++ ws ++ ys) β‘β¨ ap (take (length xs)) p β©β‘ take (length xs) (xs ++ zs) β‘β¨ take-++l (length xs) xs zs β€-refl β©β‘ take (length xs) xs β‘β¨ take-all (length xs) xs β€-refl β©β‘ xs β where us+ws-xs-same-len : length (u β· us ++ ws) β‘ length xs us+ws-xs-same-len = length-++-cancelr (u β· (us ++ ws)) xs ys zs (ap length (++-assoc (u β· us) ws ys β p)) ys-zs-same-len
A similar strategy lets us conclude that if and is a proper right factor of then is a proper right factor of
βΚ³-++-restrictr : β {ys zs : List A} β (ws xs : List A) β length ws β‘ length xs β (ws ++ ys) βΚ³ (xs ++ zs) β ys βΚ³ zs βΚ³-++-restrictr {ys = ys} {zs = zs} ws xs ws-xs-same-len (u , us , p) = ++-nonempty-βΚ³ (drop (length ws) (u β· us ++ ws)) ys zs (drop-nonempty (length ws) (u β· us ++ ws) (sβ€s len-wsβ€len-us+ws)) $ drop (length ws) (u β· us ++ ws) ++ ys β‘Λβ¨ drop-++r (length ws) (u β· us ++ ws) ys (β€-sucr len-wsβ€len-us+ws) β©β‘Λ drop β length ws β ((u β· us ++ ws) ++ ys) β‘β¨ ap! ws-xs-same-len β©β‘ drop (length xs) ((u β· us ++ ws) ++ ys) β‘β¨ ap (drop (length xs)) (++-assoc (u β· us) ws ys) β©β‘ drop (length xs) (u β· us ++ ws ++ ys) β‘β¨ ap (drop (length xs)) p β©β‘ drop (length xs) (xs ++ zs) β‘β¨ drop-++r (length xs) xs zs β€-refl β©β‘ drop (length xs) xs ++ zs β‘β¨ ap (_++ zs) (drop-all (length xs) xs β€-refl) β©β‘ zs β where len-wsβ€len-us+ws : length ws β€ length (us ++ ws) len-wsβ€len-us+ws = β€-trans (+-β€r (length us) (length ws)) $ β€-refl' (sym (length-++ us ws))
We also have a curious little result that relates right and left factors. Namely, if is a proper right factor of and is a left factor of then the corresponding left factor of is a right factor of
βΚ³-++-restrictr-βΛ‘ : β (xs ys zs : List A) β xs βΚ³ ys ++ zs β (p : ys βΛ‘ xs) β p .fst βΚ³ zs
The theorem statement is honestly harder than the proof, which gives way after a bit of algebra.
βΚ³-++-restrictr-βΛ‘ xs ys zs (u , us , us+xs=ys+zs) (vs , ys+vs=xs) = vsβzs where us+ys+vs=ys+zs : u β· us ++ ys ++ vs β‘ ys ++ zs us+ys+vs=ys+zs = u β· us ++ ys ++ vs β‘β¨ ap (u β· us ++_) ys+vs=xs β©β‘ u β· us ++ xs β‘β¨ us+xs=ys+zs β©β‘ ys ++ zs β ys+vsβys+zs : ys ++ vs βΚ³ ys ++ zs ys+vsβys+zs = u , us , us+ys+vs=ys+zs vsβzs : vs βΚ³ zs vsβzs = βΚ³-++-restrictr ys ys refl ys+vsβys+zs
Factors of powersπ
Clearly, is a proper left factor of if is nonempty.
βΛ‘-powers-inl : β (xs : List A) (k : Nat) (ys : List A) β β¦ Nonempty ys β¦ β xs βΛ‘ powers xs (suc k) ys βΛ‘-powers-inl xs k ys = βΛ‘-++-inl xs (powers xs k ys) β¦ powers-nonemptyr xs k ys auto β¦
Conversly, is a proper right factor of if is nonempty.
βΚ³-powers-inr : β (xs : List A) (k : Nat) (ys : List A) β β¦ Nonempty xs β¦ β ys βΚ³ powers xs (suc k) ys βΚ³-powers-inr xs zero ys = βΚ³-++-inr xs ys βΚ³-powers-inr xs (suc k) ys = βΚ³-trans (βΚ³-powers-inr xs k ys) $ βΚ³-++-inr xs (powers xs (suc k) ys)
Factors
of dropπ
If we remove a non-zero number of element from then we get a proper right factor.
drop-suc-βΚ³ : β (n : Nat) (xs : List A) β β¦ Nonempty xs β¦ β drop (suc n) xs βΚ³ xs drop-suc-βΚ³ zero (x β· xs) = x , [] , refl drop-suc-βΚ³ (suc n) (x β· []) = x , [] , refl drop-suc-βΚ³ (suc n) (x β· x' β· xs) = βΚ³-trans (drop-suc-βΚ³ n (x' β· xs)) $ βΚ³-++-inr (x β· []) (x' β· xs)
References
- Levi, F. W. 1944. βOn Semigroups.β Bulletin of the Calcutta Mathematical Society 36: 141β46.