可变性:直接或通过ST Monad

时间:2014-10-26 08:35:27

标签: haskell

我正在关注斯坦福算法MOOC并尝试使用Haskell来实现这些问题。许多算法需要相当多的数据处理,而纯解决方案的运行速度比人们引用命令式语言的基准测试要慢。所以我觉得我需要使用可变数据结构。

大多数Haskell数据结构似乎都有可变的等价物,但有很多关于使用它们的警告。通过IO Monad实现这些似乎很容易,但我得到的印象是“纯粹”的方式是使用ST Monad,但在后一种情况下我只看到引用的数组,其中runSTArray可用(见下面的代码)。我错过了什么吗?

main = do
    let
        inputData = [1,10,4,3,2]
    print $ elems $ runSTArray $ do
        --newListArray :: (MArray a e m, Ix i) => (i, i) -> [e] -> m (a i e)
        state <- newListArray (1, length inputData) inputData
        qsort state 1 (length inputData)
        return state

qsort :: (STArray s Int Int) -> Int -> Int -> ST s ()
qsort arr min mx =
    if mx - min < 1 then
        return ()

    else do
        p <- readArray arr min
        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

具体而言,上述与之间的有效差异是什么:

main = do
    [snip]
    arr <- newListArray (0, length inputData - 1) inputData :: IO (IOArray Int Int)
    qsort arr 0 (length inputData - 1)
    printArray arr

qsort :: (IOArray Int Int) -> Int -> Int -> IO ()
[As above]

再想一想:这个问题不过是ST和IO Monad之间的区别,那里的答案是ST是“更安全”吗?

1 个答案:

答案 0 :(得分:1)

是的,你错过了模块Data.STRef。您可以使用newSTRef创建可变变量,使用writeSTRef存储变量并使用readSTRef获取。