\import Data.Array
\import Data.Array.EPerm
\import Data.Fin (unfsuc)
\import Function
\import Function.Meta
\import Logic
\import Meta
\import Paths
\import Paths.Meta
\import Set
\func nub-split {A : \Type} {B : DecSet} {l : Array (\Sigma A B)} : EPerm l (Big (++) nil (map (\lam b => keep (\lam s => decideEq b s.2) l) (nub (map __.2 l))))
=> aux (nub (map __.2 l)) nub-isInj (later $ nub-isSurj (map __.2 l))
\where
\func aux {A : \Type} {B : DecSet} {l : Array (\Sigma A B)} (bs : Array B) (inj : IsInj bs) (l<bs : \Pi (j : Fin l.len) -> \Sigma (k : Fin bs.len) (bs k = (l j).2))
: EPerm l (Big (++) nil (map (\lam b => keep (\lam s => decideEq b s.2) l) bs)) \elim bs
| nil => \case \elim l, \elim l<bs \with {
| nil, _ => eperm-nil
| s :: l, p => \case (p 0).1
}
| b :: bs => eperm-trans keep_remove-split $ EPerm.eperm-++-right $
eperm-trans (aux bs (\lam p => unfsuc (inj p)) (\lam j =>
\have t => remove.preimage j
\in \case l<bs t.1 \with {
| (0, p) => absurd $ remove.no-element (\lam s => decideEq b s.2) {l} $ inv (pmap __.2 t.2 *> inv p)
| (suc k, p) => (k, p *> inv (pmap __.2 t.2))
})) $
EPerm.eperm-= $ pmap (Big (++) nil) $ exts \lam j => keep_remove=keep \lam p q => \case inj {0} {suc j} (q *> inv p)