我正在关注斯坦福算法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是“更安全”吗?
答案 0 :(得分:1)
是的,你错过了模块Data.STRef
。您可以使用newSTRef
创建可变变量,使用writeSTRef
存储变量并使用readSTRef
获取。