如何改变 STVector?

How to mutate an STVector?

MVector 有两种形式,IOVectorSTVector。我想编写一些使用 STVector 的函数,这样尽管在 Data.Vector.Algorithms.

中使用了快速可变向量算法,但仍可以从纯代码调用它们

a related thread 的帮助下,我已经做到了:我可以将不可变的 Vector 粘贴到可变的 ST 上下文中:

import Control.Monad.ST
import Data.Vector
import Data.Vector.Algorithms.Intro (sort)

x = fromList [1,4,2] :: Vector Int

verboseCopy :: Vector Int
verboseCopy = runST $ do v <- thaw x
                         freeze v

我只需要在解冻和冻结之间运行sort

也许令人惊讶的是,我不必 import Data.Vector.Mutable,这是定义 STVector 的地方。也许我应该使用类型签名来指定我希望 thaw 生成 STVector,但我不知道如何:如果我将 thaw 行更改为:

v <- thaw x :: Data.Vector.Mutable.STVector s Int

我收到这个错误:

• Couldn't match expected type ‘MVector
                                  (primitive-0.6.3.0:Control.Monad.Primitive.PrimState (ST s))
                                  Int’
              with actual type ‘Int’
• In the first argument of ‘freeze’, namely ‘v’

你应该可以写:

verboseCopy :: Vector Int
verboseCopy = runST $ do v <- thaw x
                         sort v
                         freeze v

给予:

> verboseCopy
[1,2,4]
>

sort v 执行排序作为对可变向量 v 的副作用,因此不需要 "save" 或 "capture" 排序结果,如果是你在担心什么。

您不需要明确键入 v。 Haskell 会将其推断为可变向量,并将其适当地视为 IOVectorSTVector,具体取决于您是在 IO 还是 ST monad 中使用它。

请注意,您收到错误的原因是您提供的类型适用于 v,但您已将其应用于 thaw x,后者具有更复杂的类型。如果你写:

verboseCopy :: Vector Int
verboseCopy = runST $ do v <- thaw x :: ST s (STVector s Int)
                         sort v
                         freeze v

然后它会输入检查。但是,同样,这是不必要的,根本不会改变行为。 Haskell已经为你想好了这个类型