Haskells `succ` 数字(浮点数)背后的基本原理

Rationale behind Haskells `succ` on numbers (floats)

得知 Haskell 将其 succ 函数定义为加一,我感到有些惊讶:

succ :: a -> a
The successor of a value. For numeric types, succ adds 1.

尽管对于整数值,这似乎是合理的,但存在一些问题:

首先,这意味着 [2.0 :: Float .. 3.0 :: Float](使用 :: Float 来确保调用没有歧义)仅包含添加到原始值的整数值,而如果使用此表达式 he/she 可能期望列表将包含两个值之间的所有浮点数;当然,这种争论更多的是关于一个人更喜欢什么。大多数程序员在这方面问题不大。

更严重的是,如果使用表达式 [2.2 :: Float .. 4.0 :: Float] 会导致 [2.2,3.2,4.2] 4.2 在这里做什么?

如果使用 +1 无法生成不同数字的浮点数(因为尾数没有足够的位来表示一个),它将无限循环。例如:

Prelude> [1e37 :: Float .. 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37-1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37+1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. pred 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.

因此,即使列表应该为空或包含一些元素,也可以生成无限量的值。

部分论点确实有点吹毛求疵,但至少对于某些人来说,假设Haskell程序员最终会犯错误是合理的。

生成下一个可表示的浮点数不是更合理的方法吗?

这样定义 succ 的依据是什么? FloatEnum 的实例是否合理?

succ函数本身的起源实际上与Haskell数据类型或枚举无关,实际上succ函数首先出现。 succ函数实际上是axiom of infinity which allows us to create numbers in the first place中的后继函数。它从未设计用于浮动 point/non-natural 数字,这就是您遇到此问题的原因。

为 Haskell 中的浮点类型修改 succ 函数可能是个好主意,您应该向邮件列表提交有关它的内容。尽管 Haskell 在 Haskell98 报告中已标准化,所以不要对更改语言抱有希望。

如果您熟悉 Haskell 的类型,请仅阅读以下内容 classes: 您提到了 [=10= 的不同可能用途] 函数,这就是为什么它被定义为 Enum 类型 class 的函数。因此,您可以轻松地重新绑定它以使用 newtype.

做一些不同的事情