Permutations of a list

Andy Fugard andyfugard@eircom.net
Mon, 14 May 2001 12:06:24 +0100


Hi all,

I'm currently teaching myself a little Haskell.  This morning I coded the 
following, the main function of which, permutate, returns all the 
permutations of a list.  (Well it seems to at least!)


insertAt :: a -> Int -> [a] -> [a]
insertAt x i xs
     | i < 0 || i > length xs  = error "invalid position"
     | otherwise               = front ++ x:back
       where (front,back) = splitAt i xs

insertAtAll :: a -> (Int,Int) -> [a] -> [[a]]
insertAtAll x (i,j) xs
     | i > j      = error "PRE: i <= j"
     | i == j     = [insertAt x i xs]
     | otherwise  = (insertAt x i xs):(insertAtAll x (i+1,j) xs)

buildPermList :: a -> [[a]] -> [[a]]
buildPermList x xs
     | length xs == 0  = []
     | otherwise       = list ++ buildPermList x (tail xs)
       where list = insertAtAll x (0, length curr) curr;
             curr = head xs

permutate :: [a] -> [[a]]
permutate xs
     | length xs == 0 = [[]]
     | otherwise      = buildPermList (last xs) (permutate (init xs))


and some test runs....

Main> permutate ""
[""]
Main> permutate "a"
["a"]
Main> permutate "ab"
["ba","ab"]
Main> permutate "abc"
["cba","bca","bac","cab","acb","abc"]


My main question is really what facilities of the language I should be 
looking at to make this code more elegant!  As you can see I currently know 
only the basics of currying, and some list operations.

Also regarding the method of generating the permutations; is there a better 
way?  The current is just "Method 1" from Knuth's TAOCP, volume 1 (3rd 
edition), p45-46.


Thanks in advance,

Andy


--
[  Andy Fugard /'andi fju:ga:d/  ]
[  Phone:  +44 (0)7901 603075    ]