In Wikibooks' Haskell, there is the following claim:
Data.List offers a sort function for sorting lists. It does not use quicksort; rather, it uses an efficient implementation of an algorithm called mergesort.
What is the underlying reason in Haskell to use mergesort over quicksort? Quicksort usually has better practical performance, but maybe not in this case. I gather that the in-place benefits of quicksort are hard (impossible?) to do with Haskell lists.
There was a related question on softwareengineering.SE, but it wasn't really about why mergesort is used.
I implemented the two sorts myself for profiling. Mergesort was superior (around twice as fast for a list of 2^20 elements), but I'm not sure that my implementation of quicksort was optimal.
Edit: Here are my implementations of mergesort and quicksort:
mergesort :: Ord a => [a] -> [a]
mergesort [] = []
mergesort [x] = [x]
mergesort l = merge (mergesort left) (mergesort right)
where size = div (length l) 2
(left, right) = splitAt size l
merge :: Ord a => [a] -> [a] -> [a]
merge ls [] = ls
merge [] vs = vs
merge first@(l:ls) second@(v:vs)
| l < v = l : merge ls second
| otherwise = v : merge first vs
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort [x] = [x]
quicksort l = quicksort less ++ pivot:(quicksort greater)
where pivotIndex = div (length l) 2
pivot = l !! pivotIndex
[less, greater] = foldl addElem [[], []] $ enumerate l
addElem [less, greater] (index, elem)
| index == pivotIndex = [less, greater]
| elem < pivot = [elem:less, greater]
| otherwise = [less, elem:greater]
enumerate :: [a] -> [(Int, a)]
enumerate = zip [0..]
Edit 2 3: I was asked to provide timings for my implementations versus the sort in Data.List
. Following @Will Ness' suggestions, I compiled this gist with the -O2
flag, changing the supplied sort in main
each time, and executed it with +RTS -s
. The sorted list was a cheaply-created, pseudorandom [Int]
list with 2^20 elements. The results were as follows:
Data.List.sort
: 0.171smergesort
: 1.092s (~6x slower thanData.List.sort
)quicksort
: 1.152s (~7x slower thanData.List.sort
)