【发布时间】:2013-12-13 00:12:25
【问题描述】:
我在 Haskell 中编写了一个函数,如下所示:
maxSumme :: [[Int]] -> Int
maxSumme [] = 0
maxSumme (x:l) = if subSumme x < maxSumme l then maxSumme l else subSumme x
subSumme :: [Int] -> Int
subSumme [] = 0
subSumme (x:l) = x + subSumme(l)
-- function call
maxSumme [[7,2,4],[5,8,1],[7,9,2]] -- with 25 innerLists
我测试过,但是这个方法很慢。如果我用 25 个包含 3 个项目的内部列表来调用它,则需要一分钟来计算 maxSumme。这不正常不是吗?我一定犯了一个错误,但我找不到它。如何优化我的方法?有没有更快的方法来做到这一点?
编辑:我认为发现了错误。我确信它是maxSumme l then maxSumme l。我每次都经常循环遍历列表,这需要很长时间。但实际上我不知道如何避免这种情况。
【问题讨论】:
-
let提升maxSumme l将时间复杂度从指数降低到线性。 CSE 在惰性语言中并不总是可以的,但在这种情况下是可以的。 -
我是 Haskell 的新手。左举和 CSE 是什么意思?如果能改成线性函数就好了
-
他的意思是将重复
subSumme x的代码包装在let ssx = subSumme x in ...中(并将subSumme x替换为ssx)。这就像以某种方式定义一个新变量。maxSumme l也是如此。 CSE 的意思是“公共子表达式消除”。如果编译器会意识到这些表达式是相同的,它可能会完成我们刚才描述的操作并优化代码中的 hell,但由于某种原因它没有(也许并不总是好的,正如菲利普建议的那样)。 -
CSE 会导致更多的共享,从而恶化渐近空间效率。因此,由于这个原因,GHC 比其他激进的生产质量编译器执行更少的 CSE,尽管它可能在处理此类情况方面做得更好。
-
@Guido 我认为问题不在于未共享的
subSumme,而是未共享的maxSumme。离开subSummeunshared 费用翻倍;离开maxSummeunshared 会使递归调用的次数加倍,这会导致递归列表长度的指数成本。
标签: haskell optimization