haskell - Haskells `succ` 数字( float )背后的基本原理

标签 haskell floating-point enumerable

得知 Haskell 将数字上的 succ 函数定义为加一时,我有点惊讶:

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

虽然对于整数值来说,这似乎是合理的,但存在一些问题:

  • 如果您定义一个只能表示偶数/奇数/素数/...数字的数字系统,换句话说,是整数子集的专用类型,会怎么样;
  • 如果您定义某种代表半数和全数的“定点数”,在这种情况下,并非所有数字都会被枚举;和
  • 对于 float 来说,这个问题最为严重。

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

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

如果使用 float ,而 +1 无法生成不同的数字(因为尾数不再有足够的位来表示 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 程序员最终会犯错误。

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

以这种方式定义 succ 的参数是什么? FloatEnum 的实例是否合理?

最佳答案

succ 函数本身的起源实际上与 Haskell 数据类型或枚举无关,事实上,succ 函数首先出现。 succ 函数实际上是 axiom of infinity 中的successor 函数。这使我们能够create numbers in the first place 。它从未设计用于浮点/非自然数,这就是您遇到此问题的原因。

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

如果您熟悉 Haskell 的类型类,请仅阅读以下内容:您提到了 succ 函数的不同可能用途,这就是为什么它被定义为函数Enum 类型类。因此,您可以轻松地重新绑定(bind)它以使用 newtype 执行不同的操作。

关于haskell - Haskells `succ` 数字( float )背后的基本原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28856516/

相关文章:

operator-keyword - 反引号运算符的固定性?

haskell - 如何找到列表的所有子序列?

ruby - 理解 Ruby 中 Enumerable 的查找函数

ruby-on-rails - 在 Ruby 中根据值从哈希集中选择一些哈希

c++ - 如何使用cout以全精度打印 double 值?

javascript - || 的和 NaN 运算符。它们到底是如何运作的?

haskell - 如何直接调用 Monad 函数?

haskell - 在 Haskell 中引用单例列表构造函数的惯用方式是什么?

c++ - 浮点比较失败且没有任何明显原因(Linux 上的 32 位 X86)

swift - 在 Swift 4 中,将 String 值类型转换为 Float 值的正确方法是什么?