我写了一个代码来计算两个无穷级数的商的系数,使用简化,如下:
main :: Int -> PInt
main 0 = 0
main n = cancel x3
where
x1 = someOtherFunction
x2 = expression involving x1
x3 = x2 - (foldr
(\y z -> z + (someOtherFunction y) * (main (n - y))) 0 [1..(n - 1)])
(我已经定义了一个名为PInt的数据,它是Num和Fractional的一个实例,并且有一个辅助函数“cancel”来执行缩减。)我的问题是x3中的表达式:它似乎不是非常有效,因为它必须计算每个主要k的较低k值。
我想也许我可以使用像
这样的实现fib = 1 : 1 : zipWith (+) fib (tail fib)
对于斐波那契数来计算上面的递归,这更有效。不幸的是,我不知道从哪里开始。
感谢您提前提供任何帮助。
P.S。代码需要花费大量时间来计算20的值,这种行为似乎意味着时间的指数增长?
答案 0 :(得分:3)
函数的内容如下所示:
main 0 = 0
main n = f [main n' | n' <- [0..n-1]]
您已经告诉过我们f
的一些信息,但对f
本身做的事情不够。即便如此,正如你所说,我们可以通过攻击递归调用来记忆一些东西:
mains = 0 : map f (inits mains)
main = (mains!!)
事实上,在您的代码中,f
的专业化似乎永远不会看到它提供的列表的头部(并且您通过计算[1..n-1]
而不是{{将其内化。 1}})。如果我们愿意,我们可以通过以下方式将此问题推到[0..n-1]
:
mains
虽然我认为把它留给mains = 0 : map (f' . drop 1) (inits mains)
-- corresponds to the specification:
-- main 0 = 0
-- main n = f' [main n' | n' <- [1..n-1]]
实际上可能更干净。