Haskell的Data.Set页面说:
关键参数被评估为WHNF
在其"严格属性"部分.
但是,我想知道为什么WHNF足以构建集合.例如,要构造一个实例Set [Int]
,我们必须深入评估其Iists列表的元素以进行比较.
扩展@ chi的评论:这只表示密钥至少被评估为WHNF.通常,一旦比较它们,它们可能会被评估,但并非总是如此.让我们调用ghc-heap-view
并查看一些示例:
Prelimaries:
~ $ ghci GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Prelude> :script /home/jojo/.cabal/share/x86_64-linux-ghc-8.0.1/ghc-heap-view-0.5.7/ghci Prelude> import qualified Data.Set as S
singleton
没有完全评估它的论点(这_bco
是一个thunk):
Prelude S> let t = [True, True && True] -- a thunk in a list Prelude S> let s1 = S.singleton t Prelude S> s1 `seq` () () Prelude S> :printHeap s1 let x1 = True() x2 = Tip() in Bin [x1,(_bco _fun)()] x2 x2 1
甚至插入另一个元素也不会完全评估列表中的第二个元素,因为可以通过查看第一个元素来区分它们:
Prelude S> let t2 = [False, False && False] -- a thunk in another list Prelude S> let s2 = S.insert t2 s1 Prelude S> s2 `seq` () () Prelude S> :printHeap s2 let x1 = True() x2 = toArray (0 words) f1 = _fun x3 = [] x4 = False() x5 = Tip() in Bin (x1 : (_bco f1)() : x3) (Bin (x4 : (_bco f1)() : x3) x5 x5 1) x5 2
但是t2
再次插入将强制该列表的第二个元素:
Prelude S> let s3 = S.insert t2 s2 Prelude S> s3 `seq` () () Prelude S> :printHeap s3 let x1 = True() x2 = [] x3 = False() x4 = Tip() in Bin (x1 : (_bco _fun)() : x2) (Bin (x3 : _bh x3 : x2) x4 x4 1) x4 2
因此Data.Set
,在存储密钥时,您无法完全依赖评估密钥.如果你想要,你需要使用,例如,(singleton $!! t1)
和(insert $!! t2)
.
(如果有人想ghc-heap-view
用ghc-vis
图表替换此答案中的输出,请随意这样做:-)).