[Haskell-cafe] Output order of Data.List.permutations?

Johannes Waldmann johannes.waldmann at htwk-leipzig.de
Sat Dec 4 19:52:50 UTC 2021


> what is the ordering of the output of
> https://hackage.haskell.org/package/base-4.16.0.0/docs/src/Data.OldList.html#permutations
> -
> and why is it not lexicographic? 


OK I think I know what's happening.


1. This function works on infinite lists:
it will permute finite prefixes, in increasing length,
while keeping the infinite suffix.

map (take 5) $ take 3 $ permutations [1 .. ] -- infinite!

[[1,2,3,4,5],[2,1,3,4,5],[3,2,1,4,5]]

This specification is incompatible with lexicographic order.
We could aim for inverse-lexicographic decrease
(i.e., `reverse $ map reverse $ permutations xs` is increasing)
but currently, it's not.


2. The program is equivalent (try it!) to

permutations xs0 =  xs0 : do
  (is', t:ts) <- splits xs0
  xs <- permutations $ reverse is'   -- reverse not needed, see below
  (pre, p:ost) <- splits xs
  return $ pre <> (t : p : ost <> ts)

with this auxiliary function
(that I sometimes wish was in Data.List)

splits xs = zip (inits xs) (tails xs)
splits "bar" = [("","bar"),("b","ar"),("ba","r"),("bar","")]

That is the form of the program that I have a chance to understand,
and prove correct. But -


3. This program contains several "append" (<>). Some are visible,
some are hidden in the  do  notation (?), and in Data.List.inits.
A series of uglification steps now transforms each "append"
into a function with an extra accumulating parameter,
and fuses some of these function calls.

E.g., "interleave" (from the source code)
is actually this function

interleave t ts xs r =
 ( map (<> ts) $ do
     (pre, p:ost) <- splits xs
     return $ pre <> [t] <> p:ost
 ) <> r

Accumulation will reverse lists.
Where reversal is not allowed, a parameter  xs :: [a]
is replaced by the function   (xs <>) :: [a] -> [a] .
In one place, reversal is kept (because it is irrelevant),
and that's why it appears in the above -
and contributes to the exotic order of output.


Truly a work of art. - I still wonder

* can we document this (perhaps find the original documentation)?
* was this necessary (or can the compiler do these transformations)?


- J.


More information about the Haskell-Cafe mailing list