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]

我得到一个解析器错误。

4

2 回答 2

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

但这仅查找单个元素,并有可能失败。

于 2013-10-18T14:16:55.440 回答
6

你有两个小错误:

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]

顺便说一句,这个函数更通用String -> [(String, a)] -> [a]

giveNumber :: Eq a => a -> [(a, t)] -> [t]
于 2013-10-18T14:24:04.847 回答