2013-10-18 42 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