相关疑难解决方法(0)

为什么差异列表比常规连接更有效?

我目前正在通过在线学习你的Haskell书籍的方式,并且已经到了一个章节,作者正在解释一些列表连接可能效率低下:例如

((((a ++ b) ++ c) ++ d) ++ e) ++ f
Run Code Online (Sandbox Code Playgroud)

据说效率低下.作者提出的解决方案是使用定义为的"差异列表"

newtype DiffList a = DiffList {getDiffList :: [a] -> [a] }

instance Monoid (DiffList a) where
    mempty = DiffList (\xs -> [] ++ xs)
    (DiffList f) `mappend` (DiffList g) = DiffList (\xs -> f (g xs))
Run Code Online (Sandbox Code Playgroud)

我很难理解为什么DiffList在某些情况下比简单串联更具计算效率.有人可以用简单的语言向我解释为什么上面的例子是如此低效,以及DiffList以什么方式解决了这个问题?

performance haskell list time-complexity difference-lists

43
推荐指数
2
解决办法
2317
查看次数

foldl懒惰怎么样?

有很多很好的问题和答案foldl,foldr以及foldl'在Haskell.

所以现在我知道:
1)foldl是懒惰的
2)不要使用,foldl因为它可以炸毁堆栈
3)使用foldl'而不是因为它是严格的(ish)

如何foldl评估:
1)创建了一大堆thunks
2)在Haskell完成创建thunk之后,thunk被减少
3)如果有太多的thunk,则溢出堆栈

我对此感到困惑:
1)为什么减少必须在所有thunk之后发生?
2)为什么foldl评估不像foldl'?这只是一个实施副作用吗?
3)从定义看,foldl看起来可以使用尾递归有效地评估 - 我如何判断一个函数是否真的会被有效地评估?如果我不希望我的程序崩溃,似乎我必须开始担心Haskell中的评估顺序.

提前致谢.我不知道我对评估的理解foldl是否正确 - 如有必要,请提出更正建议.


更新:看起来我的问题的答案与Normal Form,Weak Normal Form和Head Normal Form以及Haskell的实现有关.
但是,我仍然在寻找一个例子,更加热切地评估组合函数会导致不同的结果(崩溃或不必要的评估).

haskell lazy-evaluation fold

12
推荐指数
2
解决办法
2197
查看次数