Haskell堆和深seq库的兼容性

时间:2011-09-08 19:31:30

标签: haskell

我目前正在尝试使用hackage使用heap-1.0.0软件包的一些代码使用deepseq来确保完全严格评估计算。

我发现要使用deepseq我需要为较大表达式中涉及的类型声明NFData实例。到目前为止都很好。然后我到达Data.Heap,我用它来保存一些项目的优先级队列。突然不太好。

基本上,就我所知,我无法使deepseq和heap一起工作,因为堆的数据构造函数被隐藏起来,并且NFData实例不会在堆库本身内声明。

我的理解是否正确?是否有任何已知的方法可以使这些库协同工作并实现互操作?

提前致谢!

2 个答案:

答案 0 :(得分:2)

没有必要深入了解堆。 HeapT类型定义为

data HeapT prio val
    = Empty  -- ^ An empty 'HeapT'.
    | Tree { _rank     :: {-# UNPACK #-} !Int -- ^ Rank of the leftist heap.
           , _size     :: {-# UNPACK #-} !Int -- ^ Number of elements in the heap.
           , _priority :: !prio               -- ^ Priority of the entry.
           , _value    :: val                 -- ^ Value of the entry.
           , _left     :: !(HeapT prio val)   -- ^ Left subtree.
           , _right    :: !(HeapT prio val)   -- ^ Right subtree.
           } -- ^ A tree node of a non-empty 'HeapT'.
    deriving (Typeable)

如果您只使用普通seq,它会将堆评估为弱头正常形式,即EmptyTree构造函数。由于size字段是严格的,因此将完全评估堆的主干。

如果您在输入新项目时将其与deepseq结合使用,则将对堆进行全面评估。

let insert' item heap = item `deepseq` Data.Heap.insert item heap

let newheap = insert' item heap
in newheap `seq` do_something_else

话虽如此,如果这会导致性能下降,我不会感到惊讶。由于堆包使用Okasaki的实现,它依赖于懒惰以获得某些性能保证。试试吧,看看。

答案 1 :(得分:1)

instance NFData Heap where
       rnf x = rnf (toUnsortedList x) `seq` ()

不是最有效率的,但是通常不会发现所有内容: - )