Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么';当数字常数超出范围时,GHC投诉_Haskell - Fatal编程技术网

Haskell 为什么';当数字常数超出范围时,GHC投诉

Haskell 为什么';当数字常数超出范围时,GHC投诉,haskell,Haskell,GHC默默地忽略数值常量中超出范围的位 这种行为让我今天与一只相当奇怪的虫子搏斗: [0..256]::[Word8] -- evaluates to [0]! 我知道是什么导致了这个错误(在rot256世界中256==0)。。。。我感兴趣的是为什么GHC/Haskell在编译时不抱怨它 (这种行为对于Int也是如此——例如,18446744073709551617::Int=1) 我已经习惯于Haskell捕捉琐碎的编译时问题,当我不得不追踪到这一点时,我感到惊讶。这取决于单个Num实例的实

GHC默默地忽略数值常量中超出范围的位

这种行为让我今天与一只相当奇怪的虫子搏斗:

[0..256]::[Word8] -- evaluates to [0]!
我知道是什么导致了这个错误(在rot256世界中256==0)。。。。我感兴趣的是为什么GHC/Haskell在编译时不抱怨它

(这种行为对于Int也是如此——例如,
18446744073709551617::Int=1


我已经习惯于Haskell捕捉琐碎的编译时问题,当我不得不追踪到这一点时,我感到惊讶。

这取决于单个
Num
实例的实现。如果你表现出色

> :type 1
1 :: Num a => a
因此,Haskell只在最初将某些内容转换为泛型
Num
,然后指定一种
Word8
类型。如果你尝试

> (maxBound :: Word8) + 1
0
> maxBound :: Word8
255
这就是所谓的溢出,在许多语言中都是如此,特别是C.Haskell并没有阻止您这样做,因为在某些合法的情况下,您可能希望溢出。相反,由程序员来确保输入数据的有效性。此外,正如jozefg指出的,在编译时不可能知道每个转换是否有效


如果已经有
Eq
Bounded
Enum
,则可以实现一个
Cyclic
类,该类为您提供所需的行为:

class (Eq a, Bounded a, Enum a) => Cyclic a where
    next :: a -> a
    next a = if a == maxBound then minBound else succ a
    prev :: a -> a
    prev a = if a == minBound then maxBound else pred a

instance Cyclic Word8

> next 255 :: Word8
0
> prev 0 :: Word8
255

幸运的是,对于所有的
Integral
类型,您已经有了
Enum
Eq
,而我所知道的唯一没有
有界的
Integral
Integer
。这只是为您想要使用的每一个添加
实例循环的问题。

我怀疑诚实的答案是“因为还没有人实现它”。但我认为答案还有另一层,那就是存在一些微妙的设计问题

例如:我们如何知道
256
超出了
Word8
的范围?好吧,我想一个答案可能是编译器可能会注意到
Word8
Integral
Ord
Bounded
三者的实例。所以它可以生成一个类似

(256 :: Integer) > fromIntegral (maxBound :: Word8)
并在编译时评估此检查。问题是,突然之间,我们在编译时运行潜在的用户编写的代码(例如,
maxBound
frompintegral
、和
(>)
),这些代码可能都来自程序员可以编写的实例声明)。这可能有点危险——因为不可能知道我们是否会得到答案!所以,至少您希望在默认情况下关闭此检查,并且想必至少和模板Haskell一样难以打开


另一方面,也可以只构建一些我们“信任”的实例——如您所说的
Word8
Int
。我会发现这有点令人失望,尽管这样的补丁可能不会被拒绝。

我肯定很熟悉溢出情况。。。。我只是不想在哈斯克尔处理这件事。如果我想使用rot数,我希望它们有一个单独的类型,比如Rot8,其中
(255:Rot8)+(1::Rot8)=(0::Rot8)
,甚至可以说
(256::Rot8)=(0:Rot8)
@jamshidh自然(无符号)整数之类的东西呢?它们是一个相当常见的用例(索引),但您很少直接使用它们。相反,更常见的做法是在使用之前确保索引在适当的范围内,或者使用一个返回
的索引函数,可能是一个
值。这基本上是同一个问题。实际上,您可以创建一个
循环的
类,该类将按照您的意愿工作,它取决于
有界的
枚举
,但实现起来非常简单。我也喜欢其他人所说的,但我将答案授予您,因为这个答案最接近我当前对这一提议的更改的观点,这是-这是可能的,这将是好的。。。。这很难正确。只是出于好奇,GHC这种特殊情况下的行为是否只对文字有效,或者编译器无法获得这些信息?@GabrielGonzalez我很确定我在回答中所说的一切都适用,即使我们只对文字感兴趣。@DanielWagner你能澄清一下吗?检查数字文本如何涉及比保证终止的单个比较操作更复杂的内容?你能举一个可能出错的例子吗?请注意,我假设
maxBound
是静态已知的(即,您为其实现的类型集是静态的)。@GabrielGonzalez在我的回答中提到:所有
from integral
(>)
)和
maxBound
都是用户编写的代码,因此它们都可以发散。“rot256”我猜您的意思是“mod 256”. ;-)