2013-10-18 78 views
1

進出口尋找一個功能至極給了我一封信的所有匹配的數字,例如giveNumber "D" [("D", 5), ("A", 4) ("D", 25)] = [5,25]哈斯克爾列表綜合和模式匹配

giveNumber :: String -> [(String, a)] -> [a] 
giveNumber letter (x:xs) = [snd x | x <- xs | fst x == letter] 

我得到一個解析錯誤與... 感謝

+3

以供將來參考,它總是一個好主意後,你得到的錯誤消息。它可以讓別人看到你得到的錯誤,而不僅僅是知道你有錯誤。 – bheklilr

+0

我只是想提一下,如果你只有字母,我會使用'Char'而不是'String',另外還有值得研究的'Data.Map'。 – epsilonhalbe

回答

7

您不需要模式匹配或列表解析,因爲我認爲使用過濾器和地圖會更容易:

giveNumber :: (Eq a) => [(a, b)] -> [b] 
giveNumber x ys = map snd $ filter ((== x) . fst) ys 

儘管您可以做到這一點對你的代碼做一些小的調整:

giveNumber letter xs = [snd x | x <- xs, fst x == letter] 

這可能對你更有意義,但是兩者在執行時間上大致相同。你做錯了什麼是你在你的理解中有第二個|符號,你需要一個逗號,並且你不需要模式匹配(x:xs)作爲參數,因爲x <- xs遍歷所有的xs

或者,您也可以做到這一點更簡單地

giveNumber letter xs = [y | (x, y) <- xs, x == letter] 

的三個選項,這一次可能是最可讀的,最簡單的理解,但我喜歡的第一個最好的,因爲它是所有從作曲更高階的函數並且可以將eta簡化爲

giveNumber x = map snd . filter ((== x) . fst)) 

使ys參數隱含。

您還可能有興趣在建在lookup功能:

lookup :: Eq a => a -> [(a, b)] -> Maybe b 

但這只是查找一個元素,失敗的可能性。

+0

埃塔減少是不完全正確的!否則一個很好的答案 - 涵蓋所有的高點。 –

+0

@DanielWagner噢,你說的對,我應該使用'.'而不是'$',感謝你的支持=) – bheklilr

5

你有兩個小失誤:

1)你錯過[("D", 5), ("A", 4) , ("D", 25)]

2在列表中理解昏迷)您使用|兩次,一次也沒有

giveNumber letter xs = [snd x | x <- xs , fst x == letter] 

你可以寫一個位更漂亮:

giveNumber letter xs = [y | (x,y) <- xs , x == letter] 

由wa Y,此功能就比較一般了,然後String -> [(String, a)] -> [a]

giveNumber :: Eq a => a -> [(a, t)] -> [t] 
+1

@msietrterc最後一點非常重要。不要爲任何類型簽名添加任何更多的約束。使您的代碼更加可重用。 – itsbruce