Haskell列表理解和模式匹配

msi*_*erc 1 haskell list-comprehension pattern-matching

我正在寻找一个函数,例如,它给了我所有匹配的字母数字 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]
Run Code Online (Sandbox Code Playgroud)

我得到一个解析器错误...谢谢

bhe*_*ilr 7

您不需要模式匹配或列表推导,因为我会说使用过滤器和地图会更容易:

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

虽然您可以通过对代码进行一些小的调整来实现:

giveNumber letter xs = [snd x | x <- xs, fst x == letter]
Run Code Online (Sandbox Code Playgroud)

这可能对你更有意义,但要么在执行时间大致相同.你做错了的是你|在理解中有第二个符号,你需要一个逗号,而你不需要将匹配模式(x:xs)作为一个参数,因为x <- xs循环遍及所有xs.

或者,你可以更简单地做到这一点

giveNumber letter xs = [y | (x, y) <- xs, x == letter]
Run Code Online (Sandbox Code Playgroud)

在这三个选项中,这一个可能是最易读和最容易理解的,但我最喜欢第一个,因为它全部来自组成高阶函数,并且可以简化为

giveNumber x = map snd . filter ((== x) . fst))
Run Code Online (Sandbox Code Playgroud)

使ys参数隐式.

您可能还对lookup内置的函数感兴趣:

lookup :: Eq a => a -> [(a, b)] -> Maybe b
Run Code Online (Sandbox Code Playgroud)

但这只会查找单个元素,可能会失败.


vio*_*ior 6

你有2个小错误:

1)你错过了昏迷 [("D", 5), ("A", 4) , ("D", 25)]

2)在列表理解中你使用了|两次,而不是一次

giveNumber letter xs = [snd x | x <- xs , fst x == letter]
Run Code Online (Sandbox Code Playgroud)

你可以写一点更漂亮:

giveNumber letter xs = [y | (x,y) <- xs , x == letter]
Run Code Online (Sandbox Code Playgroud)

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

giveNumber :: Eq a => a -> [(a, t)] -> [t]
Run Code Online (Sandbox Code Playgroud)

  • @msietrterc 最后一点非常重要。不要向类型签名添加任何您绝对必须添加的约束。使您的代码更可重用。 (2认同)