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


succ :: a -> a
价值的后继者。对于数字类型,succ加1。


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


如果定义了一个只能表示偶数/奇数/质数/ ...数字的数字系统,换句话说,就是一个专用类型,它是整数的子集,该怎么办?
如果您定义了代表半数和全数的某种“定点数”,在这种情况下,并非所有数字都被列举;和
对于浮点数,问题最严重。


首先,这意味着[2.0 :: Float .. 3.0 :: Float](用于确保调用不模糊的使用过的:: Float)仅包含添加到原始值的整数值,而如果使用此表达式,则他/她可能希望列表将包含所有两个值之间的浮点;当然,这种说法更多地是关于人们的偏爱。大多数程序员在这方面没有太多问题。

更严重的是,如果使用表达式[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中的后继函数,它使我们可以create numbers in the first place。它从未设计过与浮点数/非自然数一起使用,这就是为什么您会遇到此问题。

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

仅当您熟悉Haskell的类型类时才阅读以下内容:您提到了succ函数的各种可能用法,这就是为什么将其定义为Enum类型类的函数的原因。因此,您可以轻松地将其重新绑定以使用newtype进行其他操作。

10-06 02:43