Obviously, this is just an example I'm using to understand Haskell. I'm not planning to use bubble sort for sorting, nor would I normally care to optimize away a single iteration through a list in a quadratic algorithm.
I was hoping to stop bubble sort when the list is already sorted. I wrote this code where bubble
returns, as a second item in the tuple, the boolean status that tells the caller whether any swaps were made:
bubble (x:y:ys)
| x > y = (y : fst (bubble (x:ys)), True)
| otherwise = (x : fst (bubble (y:ys)), snd (bubble (y:ys)))
bubble x = (x, False)
bubblesort xs
| snd (bubble xs) = bubblesort (fst (bubble xs))
| otherwise = fst (bubble xs)
In languages I'm familiar with, it would be horribly inefficient because bubble (y:ys)
and bubble xs
would be recomputed twice without explicit memoization. But given that Haskell functions don't have side effects, can I assume that the compiler will optimize the duplicate calls away, making my code efficient?
If not, what's a good way to write efficient bubble sort?
I have seen the approach which checks if the list is sorted:
bubbleSort (x:y:xs) = if sorted thisSort then thisSort else bubbleSort thisSort
where thisSort = (min x y) : bubbleSort ((max x y):xs)
bubbleSort x = x
sorted (x:y:xs) = if x <= y then sorted (y:xs) else False
sorted x = x
But I am trying to avoid the one additional iteration through the list (once bubbleSort
performed no swaps, one more list traversal to verify that the list is sorted is unnecessary).