Понимание списка 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]
Другие вопросы по тегам