问题描述
为什么 Haskell 范围表示法对于浮点数与整数和字符的行为不同?
Why is the behavior of the Haskell range notation different for floats than for integers and chars?
Prelude> [1, 3 .. 10] :: [Int]
[1,3,5,7,9]
Prelude> [1, 3 .. 10] :: [Float]
[1.0,3.0,5.0,7.0,9.0,11.0]
Prelude> ['a', 'c' .. 'f']
"ace"
如果最后一个元素接近上限,我会理解,但这显然不是一个舍入问题.
I would understand it if the last element was close to the upper bound, but this is obviously not a rounding issue.
推荐答案
[e1, e2 .. e3]
语法实际上是 enumFromThenTo e1 e2 e3
的语法糖,它是 Enum
类型类中的一个函数.
The syntax [e1, e2 .. e3]
is really syntactic sugar for enumFromThenTo e1 e2 e3
, which is a function in the Enum
typeclass.
Haskell 标准定义其语义如下:
对于 Int
和 Integer
类型,枚举函数有以下含义:
- 序列
enumFrom e1
是列表[e1,e1 + 1,e1 + 2,…]
. - 序列
enumFromThen e1 e2
是列表[e1,e1 + i,e1 + 2i,…]
,其中增量i
是e2 − e1
.增量可能为零或消极的.如果增量为零,则所有列表元素都是 - 序列
enumFromTo e1 e3
是列表[e1,e1 + 1,e1 + 2,…e3]
.如果e1 >,则列表为空.e3
. - 序列
enumFromThenTo e1 e2 e3
是列表[e1,e1 + i,e1 +2i,...e3]
,其中增量i
是e2 − e1
.如果增量是正数或零,列表在下一个元素出现时终止大于e3
;如果e1 >,则列表为空e3
.如果增量是负数,当下一个元素小于时,列表终止e3
;如果e1 .
- The sequence
enumFrom e1
is the list[e1,e1 + 1,e1 + 2,…]
. - The sequence
enumFromThen e1 e2
is the list[e1,e1 + i,e1 + 2i,…]
, where the increment,i
, ise2 − e1
. The increment may be zero or negative. If the increment is zero, all the list elements are the same. - The sequence
enumFromTo e1 e3
is the list[e1,e1 + 1,e1 + 2,…e3]
. The list is empty ife1 > e3
. - The sequence
enumFromThenTo e1 e2 e3
is the list[e1,e1 + i,e1 + 2i,…e3]
, where the increment,i
, ise2 − e1
. If the increment is positive or zero, the list terminates when the next element would be greater thane3
; the list is empty ife1 > e3
. If the increment is negative, the list terminates when the next element would be less thane3
; the list is empty ife1 < e3
.
这与您所期望的差不多,但是 Float
和 Double
实例的定义不同:
This is pretty much what you'd expect, but the Float
and Double
instances are defined differently:
对于Float
和Double
,enumFrom
族的语义由上述Int
的规则给出,除了当元素变得大于 e3 + i∕2
对于正增量 i
时,或者当它们变得小于 e3 + i∕2 时,列表终止
表示否定 i
.
我不确定这样做的理由是什么,所以我能给你的唯一答案是它是那样的,因为它在标准中是这样定义的.
I'm not really sure what the justification for this is, so the only answer I can give you is that it is that way because it's defined that way in the standard.
您可以通过使用整数进行枚举并在之后转换为 Float
来解决此问题.
You can work around this by enumerating using integers and converting to Float
afterward.
Prelude> map fromIntegral [1, 3 .. 10] :: [Float]
[1.0,3.0,5.0,7.0,9.0]
这篇关于Haskell 范围和浮动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!