为什么函数enumFromThenTo的行为与GHC.Enum中定义的行为不同?

时间:2015-02-28 07:47:32

标签: haskell ghc

here了解到,函数enumFromThenTo的定义是

enumFromThenTo      :: a -> a -> a -> [a]
enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]

然而,当我用下面的代码测试函数时:

import GHC.Enum
myEnumFromThenTo :: Enum a => a->a->a->[a]
myEnumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]

xs1 :: [Float]
xs1 = myEnumFromThenTo 1 3 10

xs2 :: [Float]
xs2 = enumFromThenTo 1 3 10

 -- -- | Used in Haskell's translation of @[n,n'..m]@.
-- enumFromThenTo      :: a -> a -> a -> [a]

xs1的值为[1.0,3.0,5.0,7.0,9.0],而xs2的值为[1.0,3.0,5.0,7.0,9.0,11.0]

为什么会这样?

1 个答案:

答案 0 :(得分:5)

您使用的定义只是类中的默认定义。个别实例可以自由使用不同的定义。实际上,实际实例Enum DoubleGHC.Float中定义,并使用不同的定义。

从源文件中复制相关注释:

  

Floats和Doubles的@Enum @实例略有不同寻常。 @toEnum @函数将数字截断为Int。 @ enumFrom @和@ enumFromThen @的定义允许浮点数用于算术系列:[0,0.1 .. 1.0]。然而,舍入错误使这些有点可疑。此示例可能包含10个或11个元素,具体取决于0.1的表示方式。注意:Float和Double的实例不使用@ enumFromTo @和@ enumFromThenTo @的默认方法,因为它们依赖于Int的“无损”转换。相反,我们使用1.2默认方法(在Enum将Ord作为超类的时代)(@ numericEnumFromTo @和@ numericEnumFromThenTo @下方。)