Source code on Github
------------------------------------------------------------------------
-- Properties of permuting lists with _↭_

{-# OPTIONS --safe #-}
module Prelude.Lists.Permutations where

open import Prelude.Init; open SetAsType
open import Prelude.Bifunctor
open L.Mem using (_∈_; mapWith∈)
open L.Perm using (shifts; ++⁺ˡ; ++⁺ʳ; map⁺; ↭-sym-involutive; ++-comm)
open import Prelude.Null
open import Prelude.Lists.Empty

private variable
  A B : Type 
  x y : A
  xs ys zs ws : List A
  xss yss : List (List A)

Null-↭ : xs  ys  Null xs  Null ys
Null-↭ = length≡⇒Null  L.Perm.↭-length

↭-concat⁺ : xss  yss  concat xss  concat yss
↭-concat⁺ ↭-refl = ↭-refl
↭-concat⁺ (↭-prep xs p) = ++⁺ˡ xs (↭-concat⁺ p)
↭-concat⁺ {xss = _  _  xss}{_  _  yss} (↭-swap xs ys p) = begin
  xs ++ ys ++ concat xss ↭⟨ shifts xs ys 
  ys ++ xs ++ concat xss ↭⟨ ++⁺ˡ ys $ ++⁺ˡ xs $ ↭-concat⁺ p 
  ys ++ xs ++ concat yss  where open PermutationReasoning
↭-concat⁺ (↭-trans xs↭ys ys↭zs) = ↭-trans (↭-concat⁺ xs↭ys) (↭-concat⁺ ys↭zs)

↭-concatMap⁺ : (f : A  List B)  xs  ys  concatMap f xs  concatMap f ys
↭-concatMap⁺ f = ↭-concat⁺  map⁺ f

Unique-resp-↭ : Unique {A = A} Respects _↭_
Unique-resp-↭ ↭-refl = id
Unique-resp-↭ (↭-prep _ xs↭) (x∉  p)
  = L.Perm.All-resp-↭ xs↭ x∉
   Unique-resp-↭ xs↭ p
Unique-resp-↭ (↭-swap _ _ xs↭) ((x≢y  x∉xs)  y∉xs  p)
  = (≢-sym x≢y  L.Perm.All-resp-↭ xs↭ y∉xs)
   (L.Perm.All-resp-↭ xs↭ x∉xs  Unique-resp-↭ xs↭ p)
Unique-resp-↭ (↭-trans p₁ p₂)
  = Unique-resp-↭ p₂
   Unique-resp-↭ p₁

↭-sym∘++⁺ˡ :
  (p : xs  ys)
  --——————————————————————————
   ↭-sym (++⁺ˡ zs p)
   ++⁺ˡ zs (↭-sym p)
↭-sym∘++⁺ˡ {zs = []}    p = refl
↭-sym∘++⁺ˡ {zs = x  _} p = cong (↭-prep x) (↭-sym∘++⁺ˡ p)

↭-sym∘++⁺ʳ :
  (p : xs  ys)
  --——————————————————————————
   ↭-sym (++⁺ʳ zs p)
   ++⁺ʳ zs (↭-sym p)
↭-sym∘++⁺ʳ {zs = zs} ↭-refl = refl
↭-sym∘++⁺ʳ {zs = zs} (↭-prep x p) = cong (↭-prep x) (↭-sym∘++⁺ʳ p)
↭-sym∘++⁺ʳ {zs = zs} (↭-swap x y p) = cong (↭-swap y x) (↭-sym∘++⁺ʳ p)
↭-sym∘++⁺ʳ {zs = zs} (↭-trans p q)
  rewrite ↭-sym∘++⁺ʳ {zs = zs} p
        | ↭-sym∘++⁺ʳ {zs = zs} q
        = refl

↭-sym∘++⁺ˡ∘++⁺ˡ :
  (p : xs  ys)
  --——————————————————————————
   ↭-sym (++⁺ˡ zs $ ++⁺ˡ ws p)
   (++⁺ˡ zs $ ++⁺ˡ ws $ ↭-sym p)
↭-sym∘++⁺ˡ∘++⁺ˡ {zs = zs}{ws} p
  rewrite ↭-sym∘++⁺ˡ {zs = zs} (++⁺ˡ ws p)
        | ↭-sym∘++⁺ˡ {zs = ws} p
        = refl

↭-sym∘↭-trans :
  (p : ys  xs)
  (q : ys  zs)
  --——————————————————————————
   ↭-sym (↭-trans (↭-sym p) q)
   ↭-trans (↭-sym q) p
↭-sym∘↭-trans p q = cong (↭-trans $ ↭-sym q) (↭-sym-involutive p)

↭trans∘↭-refl :
  (p : xs  ys)
  --——————————————————————————
   L.Perm.↭-trans p ↭-refl
   p
↭trans∘↭-refl = λ where
  ↭-refl  refl
  (↭-prep _ _)  refl
  (↭-swap _ _ _)  refl
  (↭-trans _ _)  refl

↭-sym∘↭trans :
  (p : xs  ys)
  (q : ys  zs)
  --——————————————————————————
   ↭-sym (L.Perm.↭-trans p q)
   L.Perm.↭-trans (↭-sym q) (↭-sym p)
↭-sym∘↭trans ↭-refl q rewrite ↭trans∘↭-refl (↭-sym q) = refl
↭-sym∘↭trans (↭-prep _ _) = λ where
  ↭-refl          refl
  (↭-prep _ _)    refl
  (↭-swap _ _ _)  refl
  (↭-trans _ _)   refl
↭-sym∘↭trans (↭-swap _ _ _) = λ where
  ↭-refl          refl
  (↭-prep _ _)    refl
  (↭-swap _ _ _)  refl
  (↭-trans _ _)   refl
↭-sym∘↭trans (↭-trans _ _) = λ where
  ↭-refl          refl
  (↭-prep _ _)    refl
  (↭-swap _ _ _)  refl
  (↭-trans _ _)   refl

↭-sym∘map⁺ :
  (f : A  B)
  (p : xs  ys)
  --——————————————————————————
   ↭-sym (map⁺ f p)
   map⁺ f (↭-sym p)
↭-sym∘map⁺ f ↭-refl = refl
↭-sym∘map⁺ f (↭-prep x p) = cong (↭-prep $ f x) (↭-sym∘map⁺ f p)
↭-sym∘map⁺ f (↭-swap x y p) = cong (↭-swap (f y) (f x)) (↭-sym∘map⁺ f p)
↭-sym∘map⁺ f (↭-trans {xs}{ys}{zs} p q)
  rewrite ↭-sym∘map⁺ {xs = xs} {ys} f p
        | ↭-sym∘map⁺ {xs = ys} {zs} f q
        = refl

-- ** _∈_
open L.Mem -- using (_∈_; mapWith∈; ∈-++⁻)
open L.Perm using (∈-resp-↭; Any-resp-↭)

∈-resp-↭∘∈-resp-↭ :
  (p : xs  ys) (q : ys  zs) (x∈ : x L.Mem.∈ xs) 
  --——————————————————————————————————————————————————————
  ∈-resp-↭ q (∈-resp-↭ p x∈)  ∈-resp-↭ (↭-trans p q) x∈
∈-resp-↭∘∈-resp-↭ p q x∈ =
  begin
      ∈-resp-↭ q (∈-resp-↭ p x∈)
    ≡⟨⟩
      ∈-resp-↭ (↭-trans p q) x∈
     where open ≡-Reasoning

Any-resp-↭∘Any-resp-↭˘ :  {x : A} {xs ys : List A}
    (p↭ : xs  ys)
    (x∈ : x  xs)
    --——————————————————————————————————————————
   (Any-resp-↭ (↭-sym p↭)  Any-resp-↭ p↭) x∈  x∈
Any-resp-↭∘Any-resp-↭˘ ↭-refl _ = refl
Any-resp-↭∘Any-resp-↭˘ (↭-prep _ _) (here _) = refl
Any-resp-↭∘Any-resp-↭˘ (↭-prep x p↭) (there p)
  = cong there $ Any-resp-↭∘Any-resp-↭˘ p↭ p
Any-resp-↭∘Any-resp-↭˘ (↭-swap _ _ _) (here _) = refl
Any-resp-↭∘Any-resp-↭˘ (↭-swap _ _ _) (there (here _)) = refl
Any-resp-↭∘Any-resp-↭˘ (↭-swap x y p↭) (there (there p))
  = cong there $ cong there $ Any-resp-↭∘Any-resp-↭˘ p↭ p
Any-resp-↭∘Any-resp-↭˘ (↭-trans p↭ p↭′) p
  rewrite Any-resp-↭∘Any-resp-↭˘ p↭′ (Any-resp-↭ p↭ p)
  = Any-resp-↭∘Any-resp-↭˘ p↭ p

Any-resp-↭˘∘Any-resp-↭ :  {x : A} {xs ys : List A}
    (p↭ : xs  ys)
    (x∈ : x  ys)
    --——————————————————————————————————————————
   (Any-resp-↭ p↭  Any-resp-↭ (↭-sym p↭)) x∈  x∈
Any-resp-↭˘∘Any-resp-↭ p↭ x∈ =
  begin
    ( Any-resp-↭ p↭
     Any-resp-↭ (↭-sym p↭)
    ) x∈
  ≡˘⟨ cong    (Any-resp-↭   Any-resp-↭ (↭-sym p↭)) x∈)
         $ L.Perm.↭-sym-involutive p↭ 
    ( Any-resp-↭ (↭-sym $ ↭-sym p↭)
     Any-resp-↭ (↭-sym p↭)
    ) x∈
  ≡⟨ Any-resp-↭∘Any-resp-↭˘ (↭-sym p↭) x∈ 
    x∈
   where open ≡-Reasoning

∈-resp-↭∘∈-resp-↭˘ :  {x : A} {xs ys : List A}
    (p↭ : xs  ys)
    (x∈ : x  xs)
    --——————————————————————————————————————————
   (∈-resp-↭ (↭-sym p↭)  ∈-resp-↭ p↭) x∈  x∈
∈-resp-↭∘∈-resp-↭˘ = Any-resp-↭∘Any-resp-↭˘

∈-resp-↭˘∘∈-resp-↭ :  {x : A} {xs ys : List A}
    (p↭ : xs  ys)
    (x∈ : x  ys)
    --——————————————————————————————————————————
   (∈-resp-↭ p↭  ∈-resp-↭ (↭-sym p↭)) x∈  x∈
∈-resp-↭˘∘∈-resp-↭ = Any-resp-↭˘∘Any-resp-↭

-- ** map
module _ {A : Type } {B : Type ℓ′} (f : A  B) where

  ∈-map-resp-↭ :  {xs ys}  xs  ys  map f xs  map f ys
  ∈-map-resp-↭ xs↭ys = ∈-resp-↭ $ map⁺ f xs↭ys

  ∈-map-resp-↭∘∈-map-resp-↭˘ :  {fx : B} {xs ys} 
    (p : xs  ys)
    (fx∈ : fx  map f xs)
    --——————————————————————————
     ( ∈-map-resp-↭ (↭-sym p)
       ∈-map-resp-↭ p
      ) fx∈
     fx∈
  ∈-map-resp-↭∘∈-map-resp-↭˘ {xs = xs}{ys} p fx∈ =
    begin
      ( ∈-map-resp-↭ (↭-sym p)
       ∈-map-resp-↭ p
      ) fx∈
    ≡⟨⟩
      ( ∈-resp-↭ (map⁺ f (↭-sym p))
       ∈-resp-↭ (map⁺ f p)
      ) fx∈
    ≡˘⟨ cong    ∈-resp-↭  $ ∈-resp-↭ (map⁺ f p) fx∈) $ ↭-sym∘map⁺ f p 
      ( ∈-resp-↭ (↭-sym $ map⁺ f p)
       ∈-resp-↭ (map⁺ f p)
      ) fx∈
    ≡⟨ ∈-resp-↭∘∈-resp-↭˘ (map⁺ f p) _ 
      fx∈
     where open ≡-Reasoning


  ∈-map⁺′ :  {y xs}  ( λ x  x  xs × y  f x)  y  map f xs
  ∈-map⁺′ = L.Any.map⁺  L.Mem.∃∈-Any

  ∈-map⁺′∘∈-map⁻ :  {y : B} {xs : List A} 
    (x∈ : y  map f xs)
    --——————————————————————————
     ( ∈-map⁺′
       ∈-map⁻ f
      ) x∈
     x∈
  ∈-map⁺′∘∈-map⁻ {y = y}{xs} x∈ =
    begin
      ( ∈-map⁺′
       ∈-map⁻ f
      ) x∈
    ≡⟨⟩
      ( LA.map⁺
       L.Mem.∃∈-Any
       find
       LA.map⁻
      ) x∈
    ≡⟨ cong LA.map⁺ $ lose∘find _ 
      ( LA.map⁺
       LA.map⁻
      ) x∈
    ≡⟨ L.Any.map⁺∘map⁻ _ 
      x∈
     where open ≡-Reasoning; module LA = L.Any

  ∈-map⁻∘∈-map⁺′ :  {y : B} {xs : List A} 
    (x∈ :  λ x  x  xs × y  f x)
    --——————————————————————————
     ( ∈-map⁻ f
       ∈-map⁺′
      ) x∈
     x∈
  ∈-map⁻∘∈-map⁺′ {y = y}{xs} x∈ =
    begin
      ( ∈-map⁻ f -- ∃x. (x ∈ xs) × (y ≡ f x)
       ∈-map⁺′  -- y ∈ map f xs
      ) x∈       -- ∃x. (x ∈ xs) × (y ≡ f x)
    ≡⟨⟩
      ( find         -- ∃x. (x ∈ xs) × (y ≡ f x)
       LA.map⁻      -- Any ((y ≡_) ∘ f) xs
       LA.map⁺      -- Any (y ≡_) (map f xs)
       L.Mem.∃∈-Any -- Any ((y ≡_) ∘ f) xs
      ) x∈           -- ∃x. (x ∈ xs) × (y ≡ f x)
    ≡⟨ cong find $ L.Any.map⁻∘map⁺ (y ≡_) (L.Mem.∃∈-Any x∈) 
      ( find         -- ∃x. (x ∈ xs) × (y ≡ f x)
       L.Mem.∃∈-Any -- Any ((y ≡_) ∘ f) xs
      ) x∈           -- ∃x. (x ∈ xs) × (y ≡ f x)
    ≡⟨ find∘lose _ _ _ 
      x∈
     where open ≡-Reasoning; module LA = L.Any


  ∈-map-resp-↭′ :  {xs ys}  xs  ys  map f xs  map f ys
  ∈-map-resp-↭′ {ys = ys} xs↭ =
    ( ∈-map⁺′                     -- y ∈ map f ys
     map₂′ (map₁ $ ∈-resp-↭ xs↭) -- (x ∈ ys) × (y ≡ f x)
     ∈-map⁻ f                    -- (x ∈ xs) × (y ≡ f x)
    )

  ∈-map-resp-↭′∘∈-map-resp-↭′˘ :  {fx : B} {xs ys} 
    (p : xs  ys)
    (fx∈ : fx  map f xs)
    --——————————————————————————
     ( ∈-map-resp-↭′ (↭-sym p)
       ∈-map-resp-↭′ p
      ) fx∈
     fx∈
  ∈-map-resp-↭′∘∈-map-resp-↭′˘ {xs = xs}{ys} p fx∈ =
    begin
      ( ∈-map-resp-↭′ (↭-sym p)
       ∈-map-resp-↭′ p
      ) fx∈
    ≡⟨⟩
      ( ∈-map⁺′                           -- (f x ∈ map f xs)
       map₂′ (map₁ $ ∈-resp-↭ (↭-sym p)) -- ∃x. (x ∈ xs) × —//—
       ∈-map⁻ f                          -- ∃x. (x ∈ ys) × (fx ≡ f x)
       ∈-map⁺′                           -- (fx ∈ map f ys)
       map₂′ (map₁ $ ∈-resp-↭ p)         -- ∃x. (x ∈ ys) × –‌//—
       ∈-map⁻ f                          -- ∃x. (x ∈ xs) × (fx ≡ f x)
      ) fx∈                               -- fx ∈ map f xs
    ≡⟨ cong (∈-map⁺′  map₂′ (map₁ $ ∈-resp-↭ (↭-sym p)))
         $ ∈-map⁻∘∈-map⁺′ (map₂′ (map₁ $ ∈-resp-↭ p) (∈-map⁻ f fx∈)) 
      ( ∈-map⁺′
       map₂′ (map₁ $ ∈-resp-↭ (↭-sym p))
       map₂′ (map₁ $ ∈-resp-↭ p)
       ∈-map⁻ f
      ) fx∈
    ≡⟨⟩
      ( ∈-map⁺′
       map₂′ (map₁ $ ∈-resp-↭ (↭-sym p)  ∈-resp-↭ p)
       ∈-map⁻ f
      ) fx∈
    ≡⟨⟩
      let x , x∈ , fx≡ = ∈-map⁻ f fx∈
      in ∈-map⁺′ (x , ∈-resp-↭ (↭-sym p) (∈-resp-↭ p x∈) , fx≡)
    ≡⟨ cong    let x , _ , fx≡ = ∈-map⁻ f fx∈
                   in ∈-map⁺′ (x ,  , fx≡))
        $ ∈-resp-↭∘∈-resp-↭˘ p _ 
      let x , x∈ , fx≡ = ∈-map⁻ f fx∈
      in ∈-map⁺′ (x , x∈ , fx≡)
    ≡⟨⟩
      ∈-map⁺′ (∈-map⁻ f fx∈)
    ≡⟨ ∈-map⁺′∘∈-map⁻ _ 
      fx∈
     where open ≡-Reasoning