Понимание списка Haskell и сопоставление с образцом
Я ищу функцию, которая дает мне все соответствующие цифры буквы, например 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]
Я получаю ошибку парсера с этим... Спасибо
2 ответа
Вам не нужно сопоставление с образцом или списки, так как я бы сказал, что это проще с фильтром и картой:
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]
Из трех вариантов этот, пожалуй, самый читаемый и самый простой для понимания, но мне больше всего нравится первый, потому что он состоит из составления функций более высокого порядка и может быть сокращен до
giveNumber x = map snd . filter ((== x) . fst))
делая ys
параметр неявный.
Вы также можете быть заинтересованы в lookup
функция, которая встроена в:
lookup :: Eq a => a -> [(a, b)] -> Maybe b
но это только поиск одного элемента, с возможностью отказа.
У вас есть 2 маленькие ошибки:
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]