Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

This is the most Monadic code I have written to date :-) and I'd welcome comments.

I'm also struck how much faster this mutable approach is than the immutable version I first wrote (see end). OK, so QuickSort is pretty much on mutability, but most algorithms seems to involve significant manipulation of elements in the data structure and immutability leads to slowness due to the endless copying of e.g. Arrays. I'm left wondering whether immutability is practical in the real world?

-- qsort :: Array -> beginning of subsection -> end of subsection
qsort :: (IOArray Int Int) -> Int -> Int -> IO ()
qsort arr min mx =
    if mx - min < 1 then do
        return ()

    else do
        p <- readArray arr min
        --foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
        final_i <- foldM (partitioner p) (min+1) [(min+1)..mx]
        swap min $ final_i - 1
        qsort arr min     (final_i-2)
        qsort arr final_i mx     

    where
        swap i j = do
            arr_i <- readArray arr i
            arr_j <- readArray arr j
            writeArray arr i arr_j
            writeArray arr j arr_i

        partitioner p i idx = do
            arr_idx <- readArray arr idx
            if arr_idx > p then
                return i
            else do
                swap i idx
                return $ i+1

I have since made the minor modifications to use an ST Monad (Gist). Not sure which is to be considered better Haskell though.

qsort :: (V.Vector Int) -> Int -> Int -> (V.Vector Int)
qsort v i j
    | len < 2 = v
    | j > len - 1 = 
        let
            -- should really switch pivot with last point in < group
            --swap 0 (i-1)
            (less, greater) = V.splitAt i v
            less_sorted = qsort (V.tail less) 1 1
            great_sorted = qsort greater 1 1
        in less_sorted V.++ cons (V.head less) great_sorted
    | vector_j > p = 
        qsort v i (j + 1)
    | otherwise = 
        qsort (swap i j) (i+1) (j+1)
    where
        len = V.length v
        p = v ! 0
        vector_i = v ! i
        vector_j = v ! j
        swap i' j' = update v $ fromList [(i', v!j),(j', v!i)]
share|improve this question
    
As we all want to make our code more efficient or improve it in one way or another, try to write a title that summarizes what your code does, not what you want to get out of a review. –  Simon Forsberg Oct 24 '14 at 9:12
    
Could you perhaps also share the immutable version? –  Petr Pudlák Oct 26 '14 at 8:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.