Section Permutations.
Variable T : eqType.
Implicit Types (x : T) (s t : seq T) (bs : seq (T * nat)) (acc : seq (seq T)).
Fixpoint incr_tally bs x :=
if bs isn't b :: bs then [:: (x, 1)] else
if x == b.1 then (x, b.2.+1) :: bs else b :: incr_tally bs x.
Definition tally s := foldl incr_tally [::] s.
Definition wf_tally :=
[qualify a bs : seq (T * nat) | uniq (unzip1 bs) && (0 \notin unzip2 bs)].
Definition tally_seq bs := flatten [seq nseq b.2 b.1 | b <- bs].
Local Notation tseq := tally_seq.
Local Fixpoint cons_perms_ perms_rec (s : seq T) bs bs2 acc :=
if bs isn't b :: bs1 then acc else
if b isn't (x, m.+1) then cons_perms_ perms_rec s bs1 bs2 acc else
let acc_xs := perms_rec (x :: s) ((x, m) :: bs1 ++ bs2) acc in
cons_perms_ perms_rec s bs1 (b :: bs2) acc_xs.
Local Fixpoint perms_rec n s bs acc :=
if n isn't n.+1 then s :: acc else cons_perms_ (perms_rec n) s bs [::] acc.
Local Notation cons_perms n := (cons_perms_ (perms_rec n) [::]).
Definition permutations s := perms_rec (size s) [::] (tally s) [::].
Let permsP s : exists n bs,
[/\ permutations s = perms_rec n [::] bs [::],
size (tseq bs) == n, perm_eq (tseq bs) s & uniq (unzip1 bs)].
Local Notation bsCA := (permEl (perm_catCA _ [:: _] _)).
Let cons_permsE : forall n x bs bs1 bs2,
let cp := cons_perms n bs bs2 in let perms s := perms_rec n s bs1 [::] in
cp (perms [:: x]) = cp [::] ++ [seq rcons t x | t <- perms [::]].
Notation perms := permutations.

Lemma permutationsE s :
0 < size s ->
perm_eq (perms s) [seq x :: t | x <- undup s, t <- perms (rem x s)].