Data.Map:如何判断我是否"需要价值严格的地图"?

met*_*eap 8 haskell

Data.Map.Lazy和之间进行选择时Data.Map.Strict,文档会告诉我们前者:

该模块的API在键中是严格的,但在值中是懒惰的.如果您需要价值严格的地图,请Data.Map.Strict改用.

对于后者同样如下:

该模块的API在键和值中都是严格的.如果您需要价值懒惰的地图,请Data.Map.Lazy改用.

经验丰富的Haskellers比我更倾向于直觉这个"需要"吗?用例 - 运行 - 完成(即不是守护程序/长期运行)命令行工具:基于readFile简单lines的自定义配置文件,其中许多(不是全部)行定义键:值对被收集到一个Map.完成后,我们会根据之后读取的其他值重写其中的许多值(由于不变性,在此过程中我们创建一个新的Map并丢弃初始化身).

(虽然在实践中这个文件可能不会经常或甚至达不到1000行,但我们只是假设为了学习某些用户不久就会这样做.)

任何给定的工具运行可能会查找大约20-100%的(重载加载,虽然懒惰eval我永远不会确定" 当真的 ")键:值对,在一次到几十次之间的任何地方.

我如何推断"价值严格"和"价值懒惰"之间的区别Data.Map?如果你愿意的话,在主流计算方面会发生什么?

从根本上说,这种哈希映射当然是关于"存储一次,多次查找"---然而,计算中的内容并非"从根本上".此外,lazy-eval的整个概念似乎归结为这个原则,为什么不总是保持价值懒惰呢?

Ing*_*ngo 8

我如何推断"价值严格"和"价值懒惰"Data.Maps之间的区别?

惰性值在Haskell中是正常的.这意味着不仅存储值,而且存储thunks(即如何计算值的配方).例如,假设您从这样的行中提取值:

tail (dropUntil (==':') line)
Run Code Online (Sandbox Code Playgroud)

然后一个值严格的映射实际上会在插入时提取值,而懒惰的映射会很高兴地记住如何获取它.这也是你得到的lookup

以下是一些优点和缺点:

  • 延迟值可能需要更多内存,不仅对于thunk本身,而且对于那里引用的数据(这里line).
  • 严格的值可能需要更多的内存.在我们的例子中,当字符串被解释为产生一些内存饥饿的结构(如列表,JSON或XML)时,情况可能如此.
  • 如果您的代码不需要每个值,则使用延迟值可能需要更少的CPU.
  • 当最终需要值时,太深的嵌套可能会导致堆栈溢出.
  • 还有一个语义上的区别:在延迟模式下,当提取值的代码失败时(如上面的那个如果行上没有':'则失败),你可能会离开,如果你只需要查看是否钥匙存在.在严格模式下,程序在插入时崩溃.

与往常一样,没有固定的措施,如:"如果您的评估值需要少于20个字节并且计算时间不到30μs,请使用strict,否则请使用lazy."

通常,您只需使用一个,当您注意到极端运行时/内存使用时,您可以尝试另一个.

  • 对我来说,语义差异是一个关键点,就是懒惰的地图可以自我指称:`让m = M.fromList [('a',1),('b',(m Map.!'a' )+1)]`,它可以让你用严格的地图做一些花哨的整洁事物 (3认同)