我对Haskell非常陌生。我一直在尝试实现n_choose_r
,但是由于某种原因,我的阶乘函数返回了奇怪的值。
Main.hs
factorial 0 = 1
factorial n = n * factorial (n-1)
subsets k list = factorial n where
n = length list
一些不同的情况
> subsets 3 [1..4]
24 // correct value
> factorial 60
8320987112741390144276341183223364380754172606361245952449277696409600000000000000
> subsets 3 [1..60]
-8718968878589280256 // wrong value
> subsets 3 [1..100]
0 // wrong value
似乎数字越长,列表越长。谁能解释?
您的factorial
函数是多态的:其类型为(Eq p, Num p) => p -> p
。当像factorial 60
那样调用它时,p
被实例化为Integer
(此选择称为“类型默认值”),它是任意精度的,没有上限。但是,length
在其输出中不是多态的:它总是返回Int
。 Haskell不会自动为您在数字类型之间转换,因此当您以factorial
的结果调用length
时,它也会使用Int
,但确实有一个上限,在您的情况下似乎是9223372036854775807
](您可以通过执行maxBound :: Int
进行验证)。要变通解决此问题,您可以自己将Int
转换为Integer
:
subsets k list = factorial (toInteger n) where
n = length list
或使用genericLength
,与length
相同,但输出类型是多态的:
import Data.List
subsets k list = factorial n where
n = genericLength list
请注意,如果您使用后一个选项,则应注意不要做任何会强迫使用Int
的事情,而不要默认为Integer
。