2013-02-22 95 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

相關問題