Using and advocating Haskell is like being Calvin (and Hobbes). To you, it's alive, real, a true delight. To those who know better, it's a stuffed tiger. - thetallguy on #haskell

the brown-dragon blog

Minimum in a Lazy Functional Language

2009-12-03

In a functional language Quicksort can be implemented in a wonderfully simple and elegant form:

qsort.hs

qsort [] = []
qsort (x:xs) = qsort lower ++ [x] ++ qsort higher
    where
        lower  = filter (<  x) xs
        higher = filter (>= x) xs

If the beauty of this implementation doesn't "get" you - simply compare it with the equivalent C code. There is no way you could call that either "simple" or "elegant" although the underlying algorithm is!

But WAIT - it gets better! In a lazy functional language finding the smallest element can now be implemented as:

    > minimum = head . qsort

And because the sort is lazy this will take O(n) instead of the expected O(n log n)!

Ponder on that a moment before moving on...

Even better, we can find the k smallest elements trivially:

    > smallest k = take k . qsort

Once I wrapped my head around that I found it utterly IN-CRE-DIBLE! This code will only sort enough elements that are needed to take the smallest k.

Designing an elegant algorithim for efficiently finding the k smallest elements has always bugged me. The superficial complexity of the sorting implementations always seemed to put me off. To do it in a single line (which is working compilable code btw) is utterly mind-boggling.

This one line automatically reduces to a partition-based general selection algorithm with no additional complexity. Plus it works perfectly, is dead simple to maintain (what are the chances of introducing a bug in that single line?), and is (to me) very beautiful.

Note: If you have compilation problems with the above code due to the monomorphism restriction add the following line:

    > minimum :: (Ord a) => [a] -> a

Other Posts

(ordered by Tags then Date)