2

Simon Marlow 在他的《Haskell 中的并行和并发编程》一书中写道:

插入操作有这一行:

putMVar m (Map.insert name number book)

这会将未计算的表达式放在 MVar 中Map.insert name number book。如果我们要连续执行许多插入操作,MVar 将建立一个大的未计算表达式链。为了获得短暂的锁定并且没有空间泄漏,我们需要使用一个技巧:

let book' = Map.insert name number book
putMVar m book'
seq book' (return ())

使用这个序列,我们在 MVar 中存储了一个未计算的表达式,但它在 putMVar 之后立即被计算。

我不明白。操作以弱头范式seq a b进行评估。a所以会有未评估的表达。正如我所看到的,只有 Map 构造函数将被评估,并且它的所有内容都将被取消评估。

4

2 回答 2

4

正如我所看到的,只有Map构造函数会被评估,所有的内容都不会被评估。

在内部,该Map类型是使用严格树实现的。要么评估整个树脊,要么不评估。这是库代码的片段:

data Map k a  = Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
              | Tip

严格性注释 ( !) 防止将未评估的值存储为子树。因此,如果我们将一个Map k a值评估为弱头范式,我们实际上会完全评估树脊。

于 2021-05-13T13:25:20.170 回答
1

MapinMap.insert不是地图构造函数。它是一个模块名称。函数insert :: Ord k => k -> a -> Map k a -> Map k a在这里被调用。由于对. _return () _ seq详情可查阅来源insert。它通过爆炸模式等进行了很多强制。

于 2021-05-13T13:26:14.827 回答