得知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
的参数是什么? Float
是Enum
的实例是否合理? 最佳答案
succ
函数本身的起源实际上与Haskell数据类型或枚举无关,实际上succ
函数是最先出现的。 succ
函数实际上是axiom of infinity中的后继函数,它使我们可以create numbers in the first place。它从未设计过与浮点数/非自然数一起使用,这就是为什么您会遇到此问题。
修改Haskell中浮点类型的succ
函数可能是一个好主意,您应该向它的邮件列表中提交一些内容。虽然,Haskell在Haskell98报告中是标准化的,所以不要对更改语言抱有希望。
仅当您熟悉Haskell的类型类时才阅读以下内容:您提到了succ
函数的各种可能用法,这就是为什么将其定义为Enum
类型类的函数的原因。因此,您可以轻松地将其重新绑定以使用newtype
进行其他操作。