这种结构是必要的实时应用 - 例如用户界面。 (用户不关心,如果点击按钮采用0.1秒或0.2秒,但他们并不在乎,如果100点击迫使一个优秀的懒惰计算,并采取10秒进行。)
我读Okasaki论文纯功能性数据结构 ,他描述了将惰性数据结构与摊余边界进入结构用相同的最坏情况下的一个有趣的一般方法界定每个操作 。 我们的想法是,使得在每个更新未计算的thunk的一些部分被强制分布计算。
我想知道,是否有任何这样的实施标准集合(的Map
, Set
等)在Haskell?
该容器包装说
每一个操作的报价或者是最坏的情况或摊销,但即使结构共享保持有效。
因此对于最坏的情况下,不保证界单个操作。 有喜欢严格的变种Data.Map.Strict
,但他们在他们的键和值严格:
键和值参数进行评估,以WHNF; 键和值进行分析,以WHNF它们存储在地图前。
没有任何关于其结构的(可能)严格。
没有任何关于其结构的(可能)严格。
去寻找来源,例如用于Data.Map.Map
-- See Note: Order of constructors
data Map k a = Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
| Tip
你看到一个Map
是完全脊柱严格的(和严格的按键,即使Data.Map.Lazy
),如果你把它评估为WHNF,完整的脊椎被强制。 这同样适用于IntMap
S, Set
S和IntSet
秒。
所以,你可以通过强制容器每次操作前WHNF防止大的thunk建设(除了映射到/包含的值)很容易。 对于所包含的价值观预防大的thunk的[时间(和空间)泄漏的常见原因]为自动为Data.XYZ.Strict
变种(警告:该值仅评估,以WHNF,如果你需要更多,你必须例如通过自己做deepseq
荷兰国际集团在手术后任何更改值immediatley),有些东西你需要处理自己与Data.XYZ.Lazy
变种。
从而
用户如果不小心点击一个按钮0.1秒需要0.2秒或,但他们并不在乎,如果100点击迫使一个优秀的懒惰计算,并采取10秒继续。
是一个很容易地避免问题与这些容器。
但是,它仍然可能是,第100次点击花费更长的时间比一般的处理,不是由于出色的懒惰计算,但由于算法(考虑两个列表,前,你出列由元素的经典队列实现dequeue (Q (x:xs) ys) = (x, Q xs ys)
在O(1),并且回到原来的地方enqueue y (Q xs ys) = Q xs (y:ys)
在O(1),以及,除了离队需要O(大小)时,前面列表为空,后面首先需要扭转,但它的O(1)摊销仍然)不改变的摊余成本。
我不知道,如果在使用的算法容器有任何这样的情况下,但它的东西要注意的。
文章来源: Haskell collections with guaranteed worst-case bounds for every single operation?