如何在Haskell中预分配向量

如何在Haskell中预分配向量,haskell,Haskell,我制作了一个涉及可变图的应用程序(我需要能够修改相互引用的对象)。为此,我使用和id并将每个对象存储在向量中(对象的id是它在向量中的位置)。向量保持在一个状态,并使用状态转换器创建一个新对象。 一切正常,但是,每个对象的创建都涉及一个snoc。当我从一个文件加载所有对象时,这会导致性能下降。有没有办法分配正确大小的向量?我的问题是,我不能使用fromList,因为我只能使用智能构造函数和状态单子创建对象 我已经(简化)的代码如下 data Box = { boxId :: Int , boxN

我制作了一个涉及可变图的应用程序(我需要能够修改相互引用的对象)。为此,我使用和id并将每个对象存储在
向量中(对象的id是它在向量中的位置)。向量保持在一个状态,并使用状态转换器创建一个新对象。
一切正常,但是,每个对象的创建都涉及一个
snoc
。当我从一个文件加载所有对象时,这会导致性能下降。有没有办法分配正确大小的向量?我的问题是,我不能使用
fromList
,因为我只能使用智能构造函数和状态单子创建对象

我已经(简化)的代码如下

data Box = { boxId :: Int , boxName :: String }
data Warehouse = { whBoxes :: Vector Box }

type WH = State Warehouse

newBox :: String -> WH Box
newBox name = do
     warehouse <- get
     let boxes = whBoxes warehouse 
     boxId = Vector.length boxes warehouse
     box = Box boxId name

     put warehouse { whBoxes = boxes `V.snoc` box }
     return box

(正如我前面所说,我简化了代码,因此它可能无法编译)。

我不确定这是否是一种改进,但您可以尝试
V.replicate
预先分配一个大的向量,然后在以后更新。“只使用newBox”和“不为每个框嗅探一次”是相互矛盾的要求-newBox硬编码每个框一个snoc,如果不允许您使用newBox以外的任何其他功能,则每个框只能使用一个snoc。或者我对“仅使用newBox”的要求解释得太严格了?我的意思是我可以重写newBox,但我希望保留相同的签名(如果可能)@mb14:什么是上下文,为什么要保留操作或签名?当前的
newBox
是向量构建的性能缺陷,而且它的类型不支持任何合理的纠正方法。我喜欢有一个智能构造函数的想法,它禁止在仓库外创建一个盒子,或者让用户分配一个不正确的id。我也有不同的方法从不同的文件格式加载盒子,我希望尽量减少重构。
import qualified Data.Csv as Csv
import qualified Data.ByteString.Lazzy as BL
import qualified Data.Vector as Vec

readBoxes :: String -> IO (WH ())
readBoxes filename = do
    csvData <- BL.readFile filename

    case Csv.decode  Csv.HasHeader csvData of
         Left err ->  do putStrLn err; return (return ())
         Right (rows) -> do
                Vec.forM_ rows $ \(style, qty) ->
                       let types = qty :: Int
                       in forM [1..qty] $   \i -> newBox style