2013-02-22 94 views
7

我不明白为什么这两个类似的列表内涵得到不同的结果:类似Haskell的列表理解产生不同的结果

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返回[]。我一定错过了一些愚蠢的东西?!

回答

6

它与

enumFromThenTo 1.0 3.0 0.0 

评估为[1.0]事实做。浮球的enumFromThenTo的规格可在http://www.haskell.org/onlinereport/haskell2010/haskellch6.html的6.3.4节中找到。

+2

对于增加花车,[a,b..c]继续前进,直到数字超过c +(b-a)/2.0。例如[1.0,2.0..4.0]是[1.0,3.0,5.0]。 – 2013-02-22 04:25:49

+0

你的例子中发生了什么2.0和4.0? – 2013-02-22 04:44:31

+0

@ Code-Guru。 Mea culpa。我的意思是[1.0,3.0 .. 4.0]。谢谢。 – 2013-02-22 04:52:29

7

首先,我把你的第一个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。另一方面,口译员推断0t2s 0中的Integer。由于参数使用的类型不同,行为可能会以非常令人惊讶的方式发生变化。特别是,在枚举列表时,应确保仅使用Integral类型,如[1,3..n]

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

+3

再次违约罢工!基本上,类型推断找到最一般的类型。问题在于数字文字被重载,所以像't2s 0'这样的表达式是模棱两可的 - 它对任何*数字类型都是有效的!由于像这样的含糊不清是常见的,我们希望能像计算器一样使用Haskell,所以我们有一个很好的方法来处理它:[默认](http://www.haskell.org/onlinereport/decls.html#sect4 .3.4)。本质上,我们只是先尝试​​'Integer',然后尝试'Double'来获得像这样的表达式。你可能想编辑一些关于这个到你的答案。 – 2013-02-22 05:55:12

+0

@TikhonJelvis我是一个Haskell新手,直到您发布此评论才知道违约。我在这里发布的答案只是来自黑客攻击OP的代码,因为我也对这些差异感到好奇。当我通过评估时,我发现了类型差异。 – 2013-02-22 05:57:39

+0

这是一个很好的时间来了解它的任何:)。当我回答一个SO问题时,我实际上首先会读到它。事实上,我就是这样捡起一大堆花絮。 – 2013-02-22 06:14:07

相关问题