Haskell长度列表+;阶乘的
我对哈斯克尔很陌生。我一直在尝试实现Haskell长度列表+;阶乘的,haskell,integer-overflow,Haskell,Integer Overflow,我对哈斯克尔很陌生。我一直在尝试实现n\u 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 832098711274139
n\u 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
似乎名单越长,数字就越不可靠。有人能解释吗?你的
阶乘函数是多态的:它有type(Eq p,Num p)=>p->p
。当您像factorial 60
那样调用它时,p
被实例化为Integer
(此选项称为“type defaulting”),这是任意精度,没有上限。但是,length
在其输出中不是多态的:它总是返回一个Int
。Haskell不会自动为您在数字类型之间进行转换,因此当您使用length
的结果调用factorial
时,它也使用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
的操作。非常感谢!我不知道Int和Integer之间有区别。只是查了一下,发现了区别。你是救命恩人