我正在尝试学习Haskell,并且我定义了以下简单的递归函数来计算阶乘。
fact n | n < 0 = error "fact only valid for non-negative integers"
| n == 0 = 1
| n > 0 = n * fact(n-1)
它适用于正整数,并且正如预期的那样,当使用负整数调用时,它会抛出我指定的错误。
问题是什么?:当我尝试将其应用于分数时,它给了我同样的错误(“事实只对非负整数有效”),例如{{1} }。为什么它给了我同样的错误,我明确指出应该只适用于n&lt; 0
答案 0 :(得分:5)
如果你给它10.5作为参数,那么第三种情况是有效的,并且函数用n = 10.5 - 1 = 9.5
递归地调用它自己。
该输入还会触发第三种情况,使用n = 8.5
进行递归调用。
等等:7.5,然后是6.5,然后是5.5,4.5,3.5,2.5,1.5,0.5
然后,在下一次迭代n = -0.5
,它触发第一种情况并产生错误。完全符合编码的一切。
如果您希望函数适用于小数,则必须(a)定义n
的{{1}}的阶乘,然后(b)对该情况进行编码。
例如,如果我要将0和1之间的数字的阶乘定义为等于1,那么该函数将如下所示:
0 < n < 1
另外,请注意:我认为上面的代码应该会给你一个警告,告知函数是部分的。这是因为编译器无法证明其中一个案例应该始终保持(并且公平地说,取决于参数类型以及fact n | n < 0 = error "fact only valid for non-negative integers"
| n >= 0 && n <= 1 = 1
| n > 0 = n * fact(n-1)
和Num
的定义,它可能不成立)。为避免这种情况,应使用Ord
子句:
otherwise