Functional Quick Sort
I spent some time today checking out Mondrian. It’s a functional language based on Haskell that works under .NET and integrates into Visual Studio.NET. For a quick overview check out this DDJ text found via Lambda the Ultimate.
One thing that strikes me as wrong about most functional language blurbs is that they all seem to use Quick Sort to demonstrate the superiority of functional languages.
It goes something like this: first they give you a Quick Sort algorithm written in C. It’s long and it’s ugly. Then comes a functional version which is short and clean. Ta-da.
There are two problems with this. First, the C version is Hoare’s version of Quick Sort that does sorting in-place. This makes it much faster and less memory intensive than the functional version. Second, if one doesn’t care about speed and memory than a similarly short function can be written just as easily in a non-functional language like C++.
You don’t believe me? Here’s the proof. To level the playing field, I first created head, tail and filter C++ template functions that operate on list<T>. Then I overloaded the operator + to concatenate lists with other lists or list elements. Those functions are part of the standard Mondrian prelude, and the operators are built into the language. In addition to that I defined template versions of the comparison operator that produces a functor objects bound to an argument.
Armed with those, here is the Quick Sort algorithm written in C++:
template <typename T>
list<T> qsort (list<T> input) {
if (input.empty ()) return list<T> ();
else {
T pivot = head (input);
list<T> before = filter (tail (input), arg < pivot);
list<T> after = filter (tail (input), arg >= pivot);
return qsort (before) + pivot + qsort (after);
}
}
For reference, here is the Quick Sort from the DDJ Mondrian text:
qsort = compare -> l ->
switch(l) {
case []: [];
case (pivot::t):
let
before = filter (x -> compare x pivot) t;
after = filter (x -> not (compare x pivot)) t;
in
(qsort compare before)
++ (pivot :: (qsort compare after));
};
Not a big difference, is is? The Mondrian version is still a bit cleaner, IMO, because of type inference, but not enough to make this a good example of functional programming. (Not to mention that type inference doesn’t mix well with function overloading.)
Also, my example uses list containers as a list data type, while Mondrian, in effect, uses iterators. But this is just me being lazy to create a functional list data type and using containers instead.
All in all, Quick Sort is a bad example of the superiority of functional languages. Something with lambda functions and function composition that cannot be done easily in traditional imperative languages would be much better.