簡體   English   中英

如何使用未裝箱的可變向量

[英]How to use Unboxed Mutable vector

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

我正在實現 QuickSort 算法並選擇Data.Vector.Unboxed.Mutable

我完全迷失了兩個問題:

  • 如何選擇正確的Monad : IOST
  • 如何從ST中獲取價值。 誰能告訴我如何打印new0

解決方案:

我從這個示例代碼中得到了一些靈感

為了更好地理解ST monad,請查看原始論文: 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

ST monad 用於當您想要獲取一些不可變數據,使其暫時可變,對其進行處理並再次使其不可變時 特別是,沒有辦法ST monad 返回可變結果(按設計)。

特別是, STVector是可變的,因此它永遠不會離開ST monad。 所以沒有辦法“打印” new0 您必須將其轉換為不可變的東西才能將其從ST monad 中返回。

如果你想改變一些東西,打印出來,再改變一點,打印出來等等,你可能想要 IO monad。 ST monad 用於使某些東西暫時可變,最終產生一個普通的即時結果。

關於s類型變量:這是一個小技巧,它強制執行可變數據不能離開ST的屬性。 runST function需要一個適用於s所有可能選擇的操作。 這意味着不可能返回任何包含s東西。 由於所有可變的東西在其類型簽名中都有s ,因此這加強了我們的保證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM