dmjio
6/3/2016 - 7:36 PM

quick-sort.hs

{-# LANGUAGE ScopedTypeVariables #-}
module QuickSort where

import           Control.Monad
import           Control.Monad.Primitive
import           Criterion
import           Criterion.Main
import           Data.List
import qualified Data.Vector                 as V
import qualified Data.Vector.Mutable         as MV
import           Data.Vector.Unboxed         hiding (filter, forM_, head,
                                              reverse, tail, (++))
import qualified Data.Vector.Unboxed.Mutable as M
import           Test.QuickCheck
import           Test.QuickCheck.Instances

qs :: Ord a => [a] -> [a]
qs [] = []
qs (x:xs) = qs left ++ [x] ++ qs right
  where
     left  = filter (<x) xs
     right = filter (>=x) xs

quickSort :: Vector Int -> Vector Int
quickSort = modify f
  where
    f :: (Ord a, PrimMonad m, Unbox a) => MVector (PrimState m) a -> m ()
    f v = qsort v 0 (M.length v - 1)
      where
        qsort a low high =
          when (low < high) $ do
            p <- partition a low high
            qsort a low (p - 1)
            qsort a (p + 1) high

        partition a low high = do
          pivot <- M.read a high
          go low (high-1) low pivot a

        go l h i pivot a =
          if l <= h
            then do
               aj <- M.read a l
               if aj <= pivot
                 then do
                   M.swap a l i
                   go (l+1) h (i+1) pivot a
                 else
                   go (l+1) h i pivot a
            else do
              M.swap a (h+1) i
              return i

test = quickCheck $ \(v :: Vector Int) ->
  (quickSort v) == (fromList $ sort (toList v))