我不明白为什么这两个相似的列表推导会给出不同的结果:
Prelude> let t2s n= [ 1/(2*i) | i <- [1,3..n]]
Prelude> t2s 0
[0.5]
Prelude> let t2s n= [ (2*i) | i <- [1,3..n]]
Prelude> t2s 0
[]
我希望两者都返回[]
论点0
。我一定是错过了什么愚蠢的东西?!
我不明白为什么这两个相似的列表推导会给出不同的结果:
Prelude> let t2s n= [ 1/(2*i) | i <- [1,3..n]]
Prelude> t2s 0
[0.5]
Prelude> let t2s n= [ (2*i) | i <- [1,3..n]]
Prelude> t2s 0
[]
我希望两者都返回[]
论点0
。我一定是错过了什么愚蠢的东西?!
首先,我将您的第一个名称更改t2s
为t1s
,以便我可以将它们同时加载到 ghci 中。查看它们每个的推断类型:
[ts.hs:2:1-33] *Main> :t t1s
t1s :: (Enum t, Fractional t) => t -> [t]
[ts.hs:2:1-33] *Main> :t t2s
t2s :: (Enum t, Num t) => t -> [t]
[ts.hs:2:1-33] *Main>
请注意,t1s
接受一个Fractional
参数,而t2s
接受一个Num
. 这意味着在 中t1s 0
,0
被推断为Double
。另一方面,解释器推断0
为 a Integer
in t2s 0
。由于用于参数的类型不同,因此行为可能会以非常令人惊讶的方式不同。特别是,您应该确保Integral
在枚举列表时仅使用类型,如[1,3..n]
.
要解决此问题,您只需为这两个函数提供显式类型签名。
这与以下事实有关
enumFromThenTo 1.0 3.0 0.0
评估为[1.0]
。Floats的规范enumFromThenTo
可以在http://www.haskell.org/onlinereport/haskell2010/haskellch6.html的第 6.3.4 节中找到。