import { Sequence } from '../../core'; import { compose } from '../../../../helper/compose'; compose(Sequence, class extends Sequence { public override permutations(): Sequence>, Sequence.Iterator]> { return Sequence.from([0]) .bind(() => { const xs = this.extract(); return xs.length === 0 ? Sequence.mempty : Sequence.from([xs]); }) .bind(xs => Sequence.mappend( Sequence.from([xs]), perms(Sequence.from(xs), Sequence.mempty))); } }); function perms(ts: Sequence, is: Sequence): Sequence>, Sequence.Iterator]> { return Sequence.Iterator.when>, Sequence.Iterator]>>( ts.iterate(), () => Sequence.mempty, tt => new Sequence>, Sequence.Iterator]>, unknown>((_, cons) => Sequence.Iterator.when( tt, () => cons(), tt => { const t = Sequence.Thunk.value(tt); const ts = Sequence.resume(Sequence.Thunk.iterator(tt)).memoize(); return cons( is.permutations() .foldr((ys, r) => interleave(Sequence.from(ys), r) , perms( ts, Sequence.mappend(Sequence.from([t]), is)))); function interleave( xs: Sequence, r: Sequence ): Sequence, Sequence.Iterator]> { return interleave_(as => as, xs, r)[1]; } function interleave_( f: (as: Sequence) => Sequence, ys: Sequence, r: Sequence ): [Sequence, Sequence.Iterator]>, Sequence, Sequence.Iterator]>] { return Sequence.Iterator.when, Sequence]>( ys.iterate(), () => [ts, r], yt => { const y = Sequence.Thunk.value(yt); const { 0: us, 1: zs } = interleave_( as => f(Sequence.mappend(Sequence.from([y]), as)), Sequence.resume(Sequence.Thunk.iterator(yt)), r); return [ Sequence.mappend(Sequence.from([y]), us), Sequence.mappend( Sequence.from([f(Sequence.mappend(Sequence.from([t]), Sequence.mappend(Sequence.from([y]), us))).extract()]), zs) ]; }); } })) .bind(xs => xs)); }