{-# OPTIONS --without-K --rewriting #-}
open import lib.Base
open import lib.Function
open import lib.PathFunctor
open import lib.PathGroupoid
open import lib.path-seq.Concat
module lib.path-seq.Split {i} {A : Type i} where
point-from-start : (n : ℕ) {a a' : A} (s : a =-= a') → A
point-from-start O {a} s = a
point-from-start (S n) {a = a} [] = a
point-from-start (S n) (p ◃∙ s) = point-from-start n s
drop : (n : ℕ) {a a' : A} (s : a =-= a') → point-from-start n s =-= a'
drop 0 s = s
drop (S n) [] = []
drop (S n) (p ◃∙ s) = drop n s
tail : {a a' : A} (s : a =-= a') → point-from-start 1 s =-= a'
tail = drop 1
private
last1 : {a a' : A} (s : a =-= a') → A
last1 {a = a} [] = a
last1 {a = a} (p ◃∙ []) = a
last1 (p ◃∙ s@(_ ◃∙ _)) = last1 s
strip : {a a' : A} (s : a =-= a') → a =-= last1 s
strip [] = []
strip (p ◃∙ []) = []
strip (p ◃∙ s@(_ ◃∙ _)) = p ◃∙ strip s
point-from-end : (n : ℕ) {a a' : A} (s : a =-= a') → A
point-from-end O {a} {a'} s = a'
point-from-end (S n) s = point-from-end n (strip s)
!- : (n : ℕ) {a a' : A} (s : a =-= a') → a =-= point-from-end n s
!- O s = s
!- (S n) s = !- n (strip s)
take : (n : ℕ) {a a' : A} (s : a =-= a') → a =-= point-from-start n s
take O s = []
take (S n) [] = []
take (S n) (p ◃∙ s) = p ◃∙ take n s
private
take-drop-split' : {a a' : A} (n : ℕ) (s : a =-= a')
→ s == take n s ∙∙ drop n s
take-drop-split' O s = idp
take-drop-split' (S n) [] = idp
take-drop-split' (S n) (p ◃∙ s) = ap (λ v → p ◃∙ v) (take-drop-split' n s)
abstract
take-drop-split : {a a' : A} (n : ℕ) (s : a =-= a')
→ ↯ s ◃∎ =ₛ ↯ (take n s) ◃∙ ↯ (drop n s) ◃∎
take-drop-split n s = =ₛ-in $
↯ s
=⟨ ap ↯ (take-drop-split' n s) ⟩
↯ (take n s ∙∙ drop n s)
=⟨ ↯-∙∙ (take n s) (drop n s) ⟩
↯ (take n s) ∙ ↯ (drop n s) =∎
private
split : {a a' : A} (s : a =-= a')
→ Σ A (λ a'' → Σ (a =-= a'') (λ _ → a'' == a'))
split {a = a} [] = (a , ([] , idp))
split {a = a} (p ◃∙ []) = (a , ([] , p))
split (p ◃∙ s@(_ ◃∙ _)) =
let (a'' , (t , q)) = split s
in (a'' , (p ◃∙ t) , q)
point-from-end' : (n : ℕ) {a a' : A} (s : a =-= a') → A
point-from-end' n {a = a} [] = a
point-from-end' O (p ◃∙ s) = point-from-end' O s
point-from-end' (S n) (p ◃∙ s) = point-from-end' n (fst (snd (split (p ◃∙ s))))
#- : (n : ℕ) {a a' : A} (s : a =-= a') → point-from-end' n s =-= a'
#- n [] = []
#- O (p ◃∙ s) = #- O s
#- (S n) (p ◃∙ s) = let (a' , (t , q)) = split (p ◃∙ s) in #- n t ∙▹ q
infix 120 _!0 _!1 _!2 _!3 _!4 _!5
_!0 = !- 0
_!1 = !- 1
_!2 = !- 2
_!3 = !- 3
_!4 = !- 4
_!5 = !- 5
0! = drop 0
1! = drop 1
2! = drop 2
3! = drop 3
4! = drop 4
5! = drop 5
infix 120 _#0 _#1 _#2 _#3 _#4 _#5
_#0 = #- 0
_#1 = #- 1
_#2 = #- 2
_#3 = #- 3
_#4 = #- 4
_#5 = #- 5
0# = take 0
1# = take 1
2# = take 2
3# = take 3
4# = take 4
5# = take 5