在什么情况下 NegativeLiterals 会改变行为?

In what cases does NegativeLiterals change behavior?

在描述 NegativeLiterals 时 School of Haskell 展示了使用语言扩展如何改变某些代码性能的示例,然后说

Other examples might actually change behavior rather than simply be less efficient

在对扩展进行了一番研究之后,我无法找到任何这些行为更改实例。我只能找到他们正在谈论的性能变化以及一些在有和没有扩展名的情况下都会出错的程序。

当启用 NegativeLiterals 扩展时,这些程序会改变它们的行为是什么?

否定字面量的区别在于,如果我们否定整数然后调用 fromInteger 或调用 fromInteger 然后否定密码域的类型。也就是说,fromInteger . negatenegate . fromInteger 不同。我希望当您处于某种类型的边界时会发生这种情况 - 一种可能会饱和而另一种可能会缠绕。

例如,我有一个非常糟糕的类型:

data Bad = Bad Integer
    deriving (Show)

instance Num Bad where
    negate (Bad a) = Bad (a + 1)
    fromInteger = Bad

结果:

*Main> (-1) :: Bad
Bad 2
*Main> :set -XNegativeLiterals
*Main> (-1) :: Bad
Bad (-1)
*Main>

考虑固定大小的类型,例如 Data.Int 中的 Int8。这是一个存储在 8 位中的有符号整数。它的可能值范围从 -128 到 127。因此,使用默认语法,文字 -128 将尝试将 128 存储在 Int8 中,然后取反它,这会导致溢出。使用NegativeLiterals,它会直接将-128构造为Int8,避免这种可能的错误。


事实证明,在 ghci 上,文字 128 会引发警告,然后由于溢出而产生 -128,因此碰巧 -128 产生正确的值。但是,我不认为这种行为是标准化的,因为 Int8 是有符号类型,所以最好不要依赖这种方式的溢出行为。

NegativeLiterals 也改变了一些表达式的解析方式。一元 - 被解释为与二进制 - 具有相同优先级的运算符(即 6),但是 NegativeLiterals 一个 - 直接(没有空格)后跟一个数字将是文字的一部分。这是一个例子,说明这会如何产生影响:

>>> :set -XNoNegativeLiterals
>>> -1 `mod` 2
-1
>>> :set -XNegativeLiterals
>>> -1 `mod` 2
1
>>> - 1 `mod` 2
-1

我从 this Whosebug 问题中得到了这个。