首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >推理懒惰

推理懒惰
EN

Stack Overflow用户
提问于 2011-03-11 23:16:57
回答 1查看 601关注 0票数 12

我有以下代码片段:

代码语言:javascript
复制
import qualified Data.Vector as V
import qualified Data.ByteString.Lazy as BL
import System.Environment
import Data.Word
import qualified Data.List.Stream as S

histogram ::  [Word8] -> V.Vector Int
histogram c = V.accum (+) (V.replicate 256 0) $ S.zip (map fromIntegral c) (S.repeat 1)

mkHistogram file = do
  hist <- (histogram . BL.unpack) `fmap` BL.readFile file
  print hist

我是这样看的:在打印之前什么都不做。在打印时,首先解开包装,然后一次映射一个fromIntegral,从而展开Word8。这些单词8中的每一个都是用1压缩的,同样是一次一个值。这些元组随后被累加器函数获取,该函数一次更新一个元组/字8。然后我们转到下一个thunk并重复,直到没有更多的内容。

这将允许在常量内存中创建直方图,但遗憾的是,这并没有发生,相反,它因堆栈溢出而崩溃。如果我尝试分析它,我看到它一直运行到最后,但是占用了很多内存(2.5Mb的文件需要300-500Mb)。内存是线性获得的,直到它被释放为止,形成了一个“漂亮的”三角形图。

我的推理在哪里出错了,我应该采取什么步骤让它在常量内存中运行?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-03-12 00:21:24

我认为问题在于Data.Vector在其元素上并不严格。因此,尽管你的推理是正确的,但当你累积直方图时,你的大腿看起来像是:

代码语言:javascript
复制
<1+(1+(1+0)) (1+(1+0)) 0 0 (1+(1+(1+(1+0)))) ... >

而不是

代码语言:javascript
复制
<3 2 0 0 4 ...>

只有在打印时才会计算出这些总和。我在文档中没有看到严格的accum函数(可惜),在seq中也没有任何地方可以挂接。摆脱这种困境的一种方法可能是使用Data.Vector.Unboxed,因为未装箱的类型是未被解除的,也就是严格的。也许你可以用你的例子作为用例来请求一个严格的accum函数。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5274700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档