Haskell程序崩溃-无限递归?where语句错误?

4
我需要计算1到n的所有阶乘的积。当我调用这个函数double_factorial(参数至少为2或3)时,它似乎被调用了一会儿,然后什么都没有发生,几秒钟后GHCi就关闭了。出了什么问题?我看不到无限递归吗?这是我的代码:
double_factorial :: Integer->Integer
double_factorial n 
    | n<0 = error "negative number is given"
    | n==0 = 1
    | otherwise = (factorial n)*(double_factorial n-1)
    where
    factorial :: Integer->Integer
    factorial n 
        | n == 0  = 1
        | otherwise = n*(factorial n-1)
3个回答

11

(double_factorial n-1) 表示 ((double_factorial n) - 1),因此是一个无限递归的问题。

(注:本翻译保留了原文中的html标签)

6

首先,因为你直接打开了GHCi,所以在GHCi停止运行时,终端窗口也会关闭。如果你从cmd(或类似的终端)中打开并使用GHCi,你就可以看到GHCi在停止运行时抛出的错误。在这种情况下,我们得到:

<interactive>: out of memory

正如你已经怀疑的那样,这确实暗示了一个无限递归问题。

因为factorial是更简单的函数,检查它的递归调用是否是罪魁祸首更容易。而实际上,factorial n - 1意味着(factorial n) - 1而不是factorial (n - 1)。在factorial n的定义中调用factorial n几乎是无限递归的典型案例。在double_factorial中我们看到了同样的问题。


为什么如果这不是一个答案,它不作为评论呢? - Mihai Maruseac
1
@MihaiMaruseac:我实际上还不能发表评论。当我正在输入我的答案时,我看到了你的答案,所以我觉得我不应该重复它。但我也认为这是有用的信息,而且我已经打了出来。这可能是我一个新手错误。 - Paul Visschers
我的错,我应该注意到你不能评论。无论如何,你可以把它变成一个答案,你会得到一些赞(这样你以后就可以评论了 :) ) - Mihai Maruseac
@MihaiMaruseac:我已经编辑了帖子,以便还包括了问题的答案。具有讽刺意味的是,现在我已经获得了足够的赞数,可以将其转换成评论。 :) - Paul Visschers

5
您有一个递归问题:f x - 1不等于f (x - 1)。解决方法是(去掉不必要的括号并添加所需的括号):
double_factorial :: Integer->Integer
double_factorial n 
    | n<0 = error "negative number is given"
    | n==0 = 1
    | otherwise = factorial n * double_factorial (n-1)
    where
    factorial :: Integer->Integer
    factorial n 
        | n == 0  = 1
        | otherwise = n * factorial (n-1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接