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
Run Code Online (Sandbox Code Playgroud)
我正在实施 QuickSort 算法,我选择 Data.Vector.Unboxed.Mutable
我对两个问题完全迷失了:
Monad:IO或STST. 谁能告诉我如何打印new0?解决方案:
我从这个示例代码中得到了一些灵感
为了更好地理解STmonad,请查看原始论文:Lazy Functional State Threads
这是一个代码片段,展示了如何使用可变向量进行快速排序:
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
Run Code Online (Sandbox Code Playgroud)
该ST单子是当你要采取一些不可改变的数据,使其暂时可变的,用它做什么,并使其再次不可改变。特别是,没有办法从STmonad返回可变结果(按设计)。
特别是,STVector是可变的,所以它永远不会离开STmonad。所以没有办法“打印出来” new0。您必须将其转换为不可变的内容才能将其从STmonad 中返回。
如果你想改变某些东西,打印出来,再改变一点,打印出来等等,你可能想要 IO monad。该ST单子是做什么暂时可变的,最终产生一个普通的immeduate结果。
关于s类型变量:这是一个小技巧,它强制执行可变数据不能离开的属性ST。该runST函数需要一个适用于每个可能选择的操作s。这意味着不可能返回任何包含s. 由于所有可变内容都包含s在其类型签名中,因此这加强了我们的保证。
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |