我怎样才能有一个严格的矢量值,比如普通类型的刘海(!)?

时间:2015-08-31 08:53:27

标签: haskell

Haskell中的一些常见performance advice是使快速数据结构“严格”,以便在创建时对结构(但不一定是其内容)进行全面评估。当我们插入一个值并且结构在缓存中时,这让我们可以做更多工作,而不是在我们查看值之前将其关闭。

使用普通数据类型,如Data.IntMap中的二进制trie,可以通过严格限制数据结构中的相关字段来实现:

data IntMap a = Bin {- ... -} !(IntMap a) !(IntMap a)
              | {- ... -}

(摘自Data.IntMap.Base来源。)

如果我想将子项存储在向量中而不是直接存储为Bin的字段,我该如何实现相同的行为?

data IntMap a = Bin {- ... -} (Vector (IntMap a))
              | {- ... -}

1 个答案:

答案 0 :(得分:2)

首先,我将回答问题的一个简单变体: 如果您的数据类型不可用,例如你想要一个Int s的严格向量, 使用Data.Vector.Unboxed。 作为免费奖励,实现允许您拥有数组",(Vector a, Vector b)的结构,甚至接口 不容易出错"结构数组",Vector (a, b)。 请参阅Wikipedia on AOS and SOA

然而,在OPs问题中,我们希望将IntMap a加入Vector,并且 IntMap不可用(或可存储或原始)。

各种选项归结为同一个想法:你必须自己seq重视。 你是否愿意 Data.Primitive.Array 或者在Data.Vector.Strict之上实施自己的Data.Vector(注意:basicClear可以是no-op as 它适用于未装箱的矢量,或者您可以使用unsafeCoerce ()作为虚拟值), 你会seq价值。这是怎么回事 Data.Map.Strict已在顶部实施 与Data.Map.Lazy相同的惰性结构。

例如 map Data.Map.Strict实现为:

map :: (a -> b) -> Map k a -> Map k b
map f = go
  where
    go Tip = Tip
    go (Bin sx kx x l r) = let !x' = f x in Bin sx kx x' (go l) (go r)

将其与Data.Map.Lazy.map

进行比较
map :: (a -> b) -> Map k a -> Map k b
map f = go where
  go Tip = Tip
  go (Bin sx kx x l r) = Bin sx kx (f x) (go l) (go r)