编写这种递归的更加​​haskellian方式?

时间:2015-09-15 02:58:39

标签: haskell recursion

我写了一个代码来计算两个无穷级数的商的系数,使用简化,如下:

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的值,这种行为似乎意味着时间的指数增长?

1 个答案:

答案 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]] 实际上可能更干净。