Simon Marlow 的《Parallel and Concurrent Programming in Haskell》一书中的严格评估示例

问题描述

Simon Marlow 在他的书“Haskell 中的并行和并发编程”中写道:

插入操作有这一行:

putMVar m (Map.insert name number book)

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

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

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

我不明白。 seq a b 操作以弱头范式计算 a。所以会有未评估的表达。正如我所看到的,只会评估 Map 构造函数,而不会评估所有内容

解决方法

正如我所见,只有 Map 构造函数会被评估,而所有内容都将不被评估。

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

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

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

, @Input() newData: any; 中的

Map 不是地图构造函数。它是一个模块名称。函数 insert :: Ord k => k -> a -> Map k a -> Map k a 在这里被调用。由于调用了 Map.insert,它的结果return () 被计算为组合 IO 操作中的下一个计算步骤之前被评估为 WHNF。详情可咨询the source of insert。它通过爆炸模式等做了很多强制。