There is a bug in the code, unless the input is expected to be a set instead of a list.
I believe the right implementation should be something like:
main :: IO ()
main = print $ quicksort [1, 123, 42, 90, 1, 23, 24, 12, 3]
quicksort [] = []
quicksort (x:xs) = quicksort left ++ [x] ++ quicksort right
where left = [ y | y <- xs, y < x ]
right = [ y | y <- xs, y >= x ]
Have you considered replacing the example entirely? A toy program that looks good but is terribly nonperformant is exactly what I'd put up if I wanted to make a Haskell-style language look bad.
Performance of a tiny code sample is not why people select one language over another. If that was the case, no one would be using anything besides assembly or C. Even in other languages, you'll use an abstraction heavy implementation for the benefit of long-term maintenance and code evolution and then performance optimise the bits that can pack a punch. Performance optimisation in any language looks ugly be it C or Haskell.
I believe the right implementation should be something like: