为什么 Int 类型 2^31 不会超出 GHCi 的范围



我正在阅读Haskell中的编程书籍,并在GHCi解释器中提供了测试示例。事实证明,GHCi和Hugs解释器中的Int类型行为存在差异。根据"Programming in Haskel"的第3章,2^31 :: Int应该超出Int类型的范围。同时,在GHCi解释器中,我得到:

Prelude> 2^31 :: Int
2147483648

而在《拥抱》中,它的行为就像书中说的那样:

Hugs> 2^31 :: Int
-2147483648

在GHCi中,我甚至可以检查结果是否是Int

Prelude> let x = 2^31 :: Int
Prelude> :type x
x :: Int
Prelude> x
2147483648

所描述的差异的来源是什么?我应该在Hugs中运行书中的示例还是使用GHCi,这似乎是学习Haskell的推荐选择?我将感谢您的帮助。

Haskell中的Int必须至少支持一系列[-2^29 .. 2^29-1],但它也可以更大。确切的大小将取决于您使用的编译器和您使用的体系结构。(你可以在2010年Haskell报告中阅读更多关于这一点的信息,这是Haskell语言的最新标准。

在 64 位计算机上使用 GHC,您将拥有一系列 [-2^63..2^63 - 1] .但即使在 32 位机器上,我相信 GHC 给你的范围也会比严格的最小值(大概是 [-2^31..2^31 - 1] )大一点。

您可以使用maxBoundminBound检查实际边界:

> maxBound :: Int
9223372036854775807
实现

之间的差异之所以出现,是因为语言定义明确允许它们以不同的方式实现这些类型。就个人而言,我会继续使用GHCi只是记住这一点,因为GHC是迄今为止最有可能使用的编译器。如果您遇到更多不一致的地方,您可以在标准中查找它们或询问某人(就像这里一样!把它想象成;)的学习经历。

该标准在这方面是灵活的,允许不同的编译器和架构以不同的方式优化其代码。我假设(但不是 100% 确定)最小范围是在考虑 32 位系统的情况下给出的,同时还允许编译器将底层 32 位值中的几个位用于其自己的内部目的,例如轻松区分数字和指针。(我知道Python和OCaml,至少,是这样做的。GHC 不需要这样做,因此它会根据其架构公开完整的 32 或 64 位。

很可能您使用的是 64 位系统,而Int具有 64 位。

试试这个:

Prelude> 2^62::Int
4611686018427387904
Prelude> 2^63::Int
-9223372036854775808

Int是机器大小的。因此,在 32 位平台上,它将在 231 处溢出。

$ ssh pi@192.168.0.3
Linux raspberrypi 3.12.28+ #709 PREEMPT Mon Sep 8 15:28:00 BST 2014 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Nov 11 12:58:20 2014 from 192.168.0.102
pi@raspberrypi:~$ ghci
GHCi, version 7.8.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 2^31 :: Int
-2147483648

请注意,Haskell报告实际上并没有具体说明Int应该有多大 - 正如Tikhon Jelvis所说,它只是保证处理229。但是GHC确实使用了所有机器整数,这通常是相当最佳的性能和需求。

最新更新