相似的Haskell列表理解结果不同

相似的Haskell列表理解结果不同,haskell,list-comprehension,Haskell,List Comprehension,我不明白为什么这两个相似的列表理解给出了不同的结果: 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 [] Prelude>设t2sn=[1/(2*i)| i t2s0 [0.5] 前奏曲>设t2sn=[(2*i)| i t2s0 [] 我希望在参

我不明白为什么这两个相似的列表理解给出了不同的结果:

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
[]
Prelude>设t2sn=[1/(2*i)| i t2s0
[0.5]
前奏曲>设t2sn=[(2*i)| i t2s0
[]

我希望在参数
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
接受一个
分数
参数,而
t2s
接受一个
Num
。这意味着在
t1s0
中,
0
被推断为
Double
。另一方面,解释器推断
0
t2s0
中的
整数由于参数不同,行为可能会有非常惊人的不同。特别是,在枚举列表时,应确保仅使用
[1,3..n]
中的
积分类型


要解决这个问题,您只需为这两个函数提供显式类型签名。

这与以下事实有关:

enumFromThenTo 1.0 3.0 0.0

计算结果为
[1.0]
。浮点数的
enumFromThenTo
规范可在的第6.3.4节中找到。

对于增加浮点数,[a,b..c]一直运行,直到数字超过c+(b-a)/2.0。例如[1.0,2.0..4.0]是[1.0,3.0,5.0]。在您的示例中,2.0和4.0发生了什么事?@code Guru Mea culpa。我的意思是说(1,3…4)谢谢。下面是一个更好的说明为什么规范类型是有意义的。考虑<代码>(0.1,0.4…0.9)< /代码>。答案是<代码> [0.1,0.4,0.7,1 ] < /代码>,它比“代码> > [0.1,0.4,0.7 ] < /代码>“更好”,在这个意义上,你的例子<代码> >代码>[1.0,3.0..0.0]
列表中“最后一个”数字的选择介于1.0和-1.0之间(-1.0表示2小于1.0,请参见?)。两者都同样接近0.0;当出现平局时,标准会选择使列表更长的一个。我不知道这个选择是任意的还是旨在减少空列表错误的可能性。
:t enumFromThenTo 1.0
enumFromThenTo 1.0::(分数t,Enum t)=>t->t->[t]
因此具体类型必须为这两个类型类定义实例。
Float
Double
都有
Enum
fractal
的实例(比如
:i Enum
:i fractal
).Defaulting再次出现!基本上,类型推断找到了最通用的类型。问题是数字文字被重载,因此像
t2s 0
这样的表达式是不明确的——它可以对任何数字类型有效!因为这样的不明确是常见的,而且我们希望能够像计算器一样使用Haskell,所以我们有一种黑客方法o处理:。本质上,我们只是先尝试
Integer
,然后尝试
Double
来处理类似的表达式。您可能想在答案中编辑一些内容。@TikhonJelvis我是Haskell新手,在您发布此评论之前不知道默认设置。我在这里发布的答案只是来自OP公司的黑客攻击de,因为我也对这些差异感到好奇。我在
:step
通过评估时发现了类型差异。现在是了解它的最佳时机:)。事实上,我也是在回答一个SO问题时第一次读到它的。事实上,我就是这样收集了一大堆这样的花絮。@TikhonJelvis我学到了很多在阅读或试图回答如此多的问题时,我也会这样做。当然,其中大部分我都忘记了。谢天谢地,当需要时,我可以将我的记忆外包给谷歌。谢谢;实际上我的代码是:sum[…],所以我不得不把事情解决(不必要的?)能够在求和项中指定此表达式的类型,因此我不确定如何才能很好地做到这一点。