2010-10-29 49 views
5

爲什麼下面的Haskell腳本不能按預期工作?Haskell中的變量

find :: Eq a => a -> [(a,b)] -> [b] 
find k t = [v | (k,v) <- t] 

鑑於find 'b' [('a',1),('b',2),('c',3),('b',4)],解釋返回[1,2,3,4],而不是[2,4]。引入新的變量,以下稱爲u,要得到這個工作:

find :: Eq a => a -> [(a,b)] -> [b] 
find k t = [v | (u,v) <- t, k == u] 

有誰知道爲什麼第一個變體不會產生期望的結果?

+0

在我之後重複一遍:Haskell中沒有變量。 ;-)這些是符號或標識符。變量意味着可變性。在Haskell中,一切都是不變的。 – 2010-10-29 16:28:02

+9

@Konrad Rudolph:Haskell 98報告在整個地方使用術語「變量」。重要的是要注意這並不意味着你可能期望的,但我認爲比標準文檔更具有人性化是非常有幫助的。 – 2010-10-29 16:31:21

+4

@Konrad魯道夫:當然你在開玩笑!爲什麼,我已經找到了關於變量的一整段內容[在Haskell中,在這裏](http://books.google.com/books?id=27dkTJFrLZIC&pg=PA111)。 – 2010-10-29 16:52:48

回答

14

Haskell 98 Report

像往常一樣,在列表綁定 推導可以陰影那些 外範圍;例如:

[ x | x <- x, x <- x ] = [ z | y <- x, z <- y]

另外一點:如果你有-Wall編譯(或專門與-fwarn-name-shadowing),你會得到以下警告:

Warning: This binding for `k' shadows the existing binding 
      bound at Shadowing.hs:4:5 

使用-Wall通常是一個好的想法 - 它往往會突出顯示在這種可能令人困惑的情況下正在發生的事情。

+0

+1引用和警告標誌暗示 – 2010-10-29 22:51:50

+0

我認爲問題不在於陰影。它首先涉及模式中標識符的含義 - 它不與具有該標識符的變量的值匹配,而是匹配任何內容並將該值與該標識符綁定到新變量 – newacct 2011-12-03 00:22:53

11

在第一個例子中的模式匹配(k,v) <- t創建兩個新的局部變量vk已填充了元組t的內容。模式匹配不會比較t與已有變量k的內容,它會創建一個新變量k(它隱藏了外部變量)。

通常,模式中不會發生任何「變量替換」,模式中的任何變量名稱都會創建新的局部變量。

3

您只能對文字和構造函數進行模式匹配。
您無法在變量上匹配。 瞭解更多here

這就是說,你可能會對查看模式感興趣。