Next lexicographic permutation of a list I began learning Haskell last week.  I wrote the following to get the next lexicographic permutation of a list.  It works perfectly but I feel like I'm just writing a c# method.  My long list of where commands just feels like an imperative approach.  I would appreciate any feedback if this solution is indeed the way most people would write something like this in haskell:

-- Finds the end of a list that is monotonically decreasing (swap)
-- Pivot is the index just before it. (pivot)
-- exchanges the smallest value &gt; pivot in swap with pivot
-- reverses the swap with the pivot in it, and concatenates the new permutation
nextPerm :: (Ord a,Num a) =&gt; [a] -&gt; [a]
nextPerm [] = []
nextPerm a = if pivotIndex == (-1) then a 
             else prePivot ++ [swapVal] ++ swapWithPivot
             where
                 swap = foldl (\acc x -&gt; if x&lt;=(last acc) then acc ++ [x] else [x]) [(-1)] a
                 pivotIndex = (length a) - (length swap) - 1
                 prePivot = take pivotIndex a
                 pivotVal = a !! pivotIndex
                 swapVal = foldl1 (\acc x -&gt; if x &gt; pivotVal then x else acc) swap
                 swapWithPivot = insert pivotVal $ delete swapVal $ reverse swap
I'm a beginner at Haskell as well, so take my opinion with a big rock of salt.

nextPerm :: (Ord a, Num a) =&gt; [a] -&gt; [a]
nextPerm [] = []
nextPerm a


I wouldn't use a as a type variable and a variable at the same time. 
I like to name lists xs, ys, cs, etc. I feel this is more descriptive, and it works well with pattern-matching, e.g. (x:xs), where x is the head of the list, xs is the tail.

swap = foldl (\acc x -&gt; if x &lt;= (last acc) then acc ++ [x] else [x]) [(-1)] a

Here you are going through the list from the front. When you use last, the program has to go through the whole list, because lists are kind of like linked lists, think [1,2,3] = 1 : 2 : 3 : [], so accessing an element takes \$O(n) \$ time.
For the same reason, (++) is expensive, while (:) is cheap. Try running swap on a list of \$ 10^5 \$ size; it's slow.

Other than the speed factor, I think your implementation is OK!

If you want to make it faster, first of all you should change swap. For example, first reverse the list, then work on it - as lists are made to be accessed from the front, not the back. Let me show you an improved version of swap along with a few other changes. 

nextPerm :: Ord a =&gt; [a] -&gt; [a]
nextPerm xs
  | null xs || pivotIndex == -1 = xs
  | otherwise = prePivot ++ swapVal : swapWithPivot
  where pivotIndex = length xs - length swap - 1
        prePivot = take pivotIndex xs
        pivotVal = xs !! pivotIndex
        swapVal = foldl1 (\acc x -&gt; if x &gt; pivotVal then x else acc) swap
        swapWithPivot = insert pivotVal . delete swapVal . reverse $ swap
        swap = reverse . fmap fst 
                       . takeWhile (uncurry (&gt;=)) 
                       . (&lt;*&gt;) zip (\ls -&gt; head ls:ls) 
                       . reverse $ xs


As you can see, this way, you don't even need to restrict yourself to the class Num.
To make it even better, figure out how to use span instead of take, and takeWhile. If you do that, you won't even need indexing anymore.   Use Hoogle, play around in ghci, look at types using :t &lt;typename&gt; e.g. :t span - type signatures (and names) will usually tell you what a function does.

Lists are weak at random access, but kind of good at being sliced up; therefore I'd definitely drop the whole indexing thing.

Anyway, I will include how I'd write it, hopefully it'll give you some new ideas. 

nextPerm' :: Ord a =&gt; [a] -&gt; [a]
nextPerm' = uncurry (++) . uncurry swap
                         . (fmap fst *** fmap fst)
                         . span (uncurry (&gt;=))
                         . (&lt;*&gt;) zip (\ls -&gt; head ls:ls)
                         . reverse
    where swap rpost [] = ([], rpost)
          swap rpost (pivot:rpre) = (reverse rpre, ins . span (&lt;= pivot) $ rpost)
              where ins (le,[])   = le ++ [pivot]
                    ins (le,a:as) = a:le ++ pivot:as


If you want to test an implementation, issue

(sort . permutations $ [1,2,3,4,5]) == (take 120 $ iterate nextPerm [1,2,3,4,5])


If it works, the result will be True.