为函数应用于分数时显示的负数指定的错误.为什么?

Cur*_*arn 0 recursion haskell

我正在尝试学习Haskell,并且我定义了以下简单的递归函数来计算阶乘.

fact n | n < 0 = error "fact only valid for non-negative integers"
       | n == 0 = 1
       | n > 0 = n * fact(n-1)
Run Code Online (Sandbox Code Playgroud)

它适用于正整数,并且正如预期的那样,当使用负整数调用时,它会抛出我指定的错误.

问题是什么?:当我尝试将它应用于Fractional时,它给了我同样的错误("事实只对非负整数有效"),例如fact 10.5.为什么它给了我同样的错误,我明确指出应该只适用于n <0的情况.

Fyo*_*kin 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)定义什么是nfor 的阶乘0 < n < 1,然后(b)编码该情况.

例如,如果我要将0和1之间的数字的阶乘定义为等于1,那么该函数将如下所示:

fact n | n < 0 = error "fact only valid for non-negative integers"
       | n >= 0 && n <= 1 = 1
       | n > 0 = n * fact(n-1)
Run Code Online (Sandbox Code Playgroud)

另外,旁注:我认为上面的代码应该给你一个警告,函数是部分的.这是因为编译器无法证明其中一个案例应该始终保持(并且公平地说,取决于参数类型和它的定义,Num并且Ord它可能不成立).为避免这种情况,应该使用一个otherwise条款:

fact n | n < 0 = error "fact only valid for non-negative integers"
       | n >= 0 && n <= 1 = 1
       | otherwise = n * fact(n-1)
Run Code Online (Sandbox Code Playgroud)