module ListExtras where
open import Data.List
open import Data.Nat
open import Data.Fin using (Fin; zero; suc)
open import Data.Product
open import Data.List.Properties using (++-assoc) renaming (++-identityʳ to ++-id-right; ∷-injectiveˡ to ∷-inj₁; ∷-injectiveʳ to ∷-inj₂) public
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym; cong; trans; subst) public
open import Simple-list-solver using (list-solve; bla) renaming (id to :[]; _⊕_ to _:++_; _⊜_ to _:≡_) public
nil-cons-absurd : ∀ {a b} {A : Set a} {B : Set b} (xs : List A) {y zs}
→ [] ≡ xs ++ y ∷ zs
→ B
nil-cons-absurd [] ()
nil-cons-absurd (x ∷ Γ) ()
singleton-lemma : ∀ {a} {A : Set a} (ys : List A) {x₁ x₂ zs}
→ [ x₁ ] ≡ ys ++ x₂ ∷ zs
→ ys ≡ [] × x₁ ≡ x₂ × zs ≡ []
singleton-lemma [] refl = refl , refl , refl
singleton-lemma (_ ∷ Γ) p = nil-cons-absurd Γ (∷-inj₂ p)
data MatchCons {a} {A : Set a}
(xs : List A) (y : A) (zs : List A)
(us : List A) (v : A) (ws : List A) : Set a where
here
: xs ≡ us
→ y ≡ v
→ zs ≡ ws
→ MatchCons xs y zs us v ws
before : (ms : List A)
→ xs ≡ us ++ v ∷ ms
→ ms ++ y ∷ zs ≡ ws
→ MatchCons xs y zs us v ws
after : (ms : List A)
→ zs ≡ ms ++ v ∷ ws
→ us ≡ xs ++ y ∷ ms
→ MatchCons xs y zs us v ws
match-cons : ∀ {a} {A : Set a}
→ (xs us : List A)
→ {zs ws : List A}
→ {y v : A}
→ xs ++ y ∷ zs ≡ us ++ v ∷ ws
→ MatchCons xs y zs us v ws
match-cons [] [] refl = here refl refl refl
match-cons [] (u ∷ us) p = after us (∷-inj₂ p) (cong (λ i → i ∷ us) (sym (∷-inj₁ p)))
match-cons (x ∷ xs) [] p = before xs (cong (λ i → i ∷ xs) (∷-inj₁ p)) (∷-inj₂ p)
match-cons (x ∷ xs) (u ∷ us) p with ∷-inj₁ p | match-cons xs us (∷-inj₂ p)
... | refl | here refl refl refl = here refl refl refl
... | refl | before ms refl refl = before ms refl refl
... | refl | after ms refl refl = after ms refl refl
match-cons-2 : ∀ {a} {A : Set a}
→ (xs xs′ us : List A)
→ {zs ws : List A}
→ {y v : A}
→ xs ++ xs′ ++ y ∷ zs ≡ us ++ v ∷ ws
→ MatchCons (xs ++ xs′) y zs us v ws
match-cons-2 [] [] [] refl = here refl refl refl
match-cons-2 [] (x ∷ xs′) [] p = before xs′ (cong (λ i → i ∷ xs′) (∷-inj₁ p)) (∷-inj₂ p)
match-cons-2 (x ∷ xs) xs′ [] p = before
(xs ++ xs′)
(cong (λ i → i ∷ xs ++ xs′) (∷-inj₁ p))
(trans (++-assoc xs xs′ _) (∷-inj₂ p))
match-cons-2 [] [] (u ∷ us) p = after
us
(∷-inj₂ p)
(sym (cong (λ i → i ∷ us) (∷-inj₁ p)))
match-cons-2 [] (x ∷ xs′) (u ∷ us) p with ∷-inj₁ p | match-cons xs′ us (∷-inj₂ p)
... | refl | here refl refl refl = here refl refl refl
... | refl | before ms refl refl = before ms refl refl
... | refl | after ms refl refl = after ms refl refl
match-cons-2 (x ∷ xs) xs′ (u ∷ us) p with ∷-inj₁ p | match-cons-2 xs xs′ us (∷-inj₂ p)
... | refl | here refl refl refl = here refl refl refl
... | refl | before ms pf refl = before ms (cong (λ is → x ∷ is) pf) refl
... | refl | after ms refl refl = after ms refl refl
data FindCons {a} {A : Set a}
(xs : List A) (ys : List A)
(us : List A) (v : A) (ws : List A) : Set a where
in-first : (ms : List A)
→ xs ≡ us ++ v ∷ ms
→ ms ++ ys ≡ ws
→ FindCons xs ys us v ws
in-second : (ms : List A)
→ ys ≡ ms ++ v ∷ ws
→ xs ++ ms ≡ us
→ FindCons xs ys us v ws
find-cons : ∀ {a} {A : Set a}
→ (xs : List A) {ys : List A}
→ (us : List A) {v : A} {ws : List A}
→ xs ++ ys ≡ us ++ v ∷ ws
→ FindCons xs ys us v ws
find-cons [] [] refl = in-second [] refl refl
find-cons [] (u ∷ us) refl = in-second (u ∷ us) refl refl
find-cons (x ∷ xs) [] refl = in-first xs refl refl
find-cons (x ∷ xs) (x₁ ∷ us) p with ∷-inj₁ p | find-cons xs us (∷-inj₂ p)
... | refl | in-first ms refl refl = in-first ms refl refl
... | refl | in-second ms refl refl = in-second ms refl refl