import Control.Monad.ST
import Data.STRef
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as MV
-- what the heck is that s?
new0 :: (MV.Unbox a, Num a) => ST s (MV.STVector s a)
new0 = do
v <- MV.new 10
MV.write v 1 10
MV.write v 2 10
return v
new1 :: (MV.Unbox a) => IO (MV.IOVector a)
new1 = MV.new 10
new2 :: (MV.Unbox a, Num a) => IO (MV.STVector RealWorld a)
new2 = do
v <- MV.new 10
MV.write v 1 10
return v
I'm implementing the QuickSort algorithm and I choose Data.Vector.Unboxed.Mutable
I'm completely lost regarding two issues:
- How to choose the right
Monad
:IO
orST
- How to get the value out of
ST
. Could anyone show me how to printnew0
?
Solutions:
I got some inspirations from this example code
For a good understanding of ST
monad, check the original paper: Lazy Functional State Threads
Here's a code snippet showing how to use mutable vectors for quicksort:
import Control.Monad.Primitive
import Control.Monad.ST (runST)
import Prelude hiding (read)
import Data.List (partition)
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as M
partitionV :: (PrimMonad m, Ord a, V.Unbox a)
=> M.MVector (PrimState m) a -> Int -> Int -> m Int
partitionV v p r = do
let i = p
x <- M.unsafeRead v r
go i p x
where
go i j x | j < r = do
jv <- M.unsafeRead v j
if jv < x
then M.unsafeSwap v i j >> go (i+1) (j+1) x
else go i (j+1) x
go i _ _ = do
M.unsafeSwap v i r
return i
quickSortV :: (PrimMonad m, Ord a, V.Unbox a)
=> M.MVector (PrimState m) a -> m ()
quickSortV v | M.length v < 2 = return ()
quickSortV v = do
i <- partitionV v 0 (M.length v - 1)
quickSortV (M.unsafeSlice 0 i v)
quickSortV (M.unsafeSlice (i + 1) (M.length v - 1 - i) v)
-- note the difference between for loop and recursive call
test l = runST $ do
mv <- V.thaw l
quickSortV mv
V.freeze mv
quickSort :: (Ord a) => [a] -> [a]
quickSort [] = []
quickSort (x : xs) =
let (lt, gt) = partition (<= x) xs
in quickSort lt ++ [x] ++ quickSort gt