【发布时间】:2013-07-19 22:32:50
【问题描述】:
只是为了好玩,我想看看如果我在 Haskell 中将一个函数定义为 Int -> Int 会发生什么,我知道它会溢出并且必须返回一个 Integer。考虑以下几点:
factorial :: Int -> Int
factorial n = product [1..n]
现在我知道,如果我运行 factorial 50,我会得到一个在 factorial 的“codomain”之外的数字。由于 Haskell 的类型非常强,我希望它会返回错误。相反,GHCi 返回一个奇怪的否定 Int:
ghci> factorial 50
-3258495067890909184
请注意
ghci> maxBound :: Int
9223372036854775808
因为我在 64 位上运行。
我觉得这种行为有点可怕:为什么 Haskell 不引发错误?为什么factorial 50 返回一个随机负数?任何澄清将不胜感激。
【问题讨论】:
-
每次计算时检查一个 int 是否超出范围是完全荒谬的并且会破坏性能。如果您有可能超出范围的功能,请使用
Integer。阶乘是这样做的合适时机,因为它可以如此迅速地创建大值。 -
我显然知道它会提前超出范围(你读过帖子吗?)。问题是为什么我得到一个可疑的负数而不是 Int 的上限。
-
您为什么希望它返回
Integer?这是一个有效的Int -> Int -> Int,而您的答案是product在Int上运行,是Int。根据Int的所有定义,您的答案是非常合法的Int。 -
顺便说一下,它不是一个随机的负数。这正是人们所期望的(对于 GHC 上的 64 位
Ints),50!以2^64为模的余数在-2^63到2^63-1的范围内。 -
@JustinL。我不一定期望它会返回
Int。我只知道它会溢出。