Как извлечь термины конкретного конструктора данных из списка в Haskell
Общей проблемой, которую я получил в Haskell, является извлечение всех терминов в списке, принадлежащем конкретному конструктору данных, и мне интересно, есть ли какие-то лучшие способы, чем то, как я это делаю в данный момент.
Скажем, вы получили
data Foo = Bar | Goo
список
foos = [Bar, Goo, Bar, Bar, Goo]
и хотите извлечь все Goo
из foos
. На данный момент я обычно делаю что-то вроде
goos = [Goo | Goo <- foos]
и все хорошо. Проблема в том, когда Goo
получил кучу полей, и я вынужден написать что-то вроде
goos = [Goo a b c d e f | Goo a b c d e f <- foos]
который далеко не идеален. Как обычно вы справляетесь с этой проблемой?
Ответы
Ответ 1
Похоже, есть две части этого вопроса:
- Есть ли более простой способ сделать сопоставление с образцом
- Являются ли перечисления здесь здесь?
Во-первых, там есть лучший способ сопоставления полей, которые вам не нужны:
goos = [ x | [email protected](Goo {}) <- foos]
Во-вторых, использование списков - это совершенно кропотливый способ записи таких фильтров. Например, в базовой библиотеке catMaybes определяется как:
catMaybes :: [Maybe a] -> [a]
catMaybes ls = [x | Just x <- ls]
(из базовой библиотеки). Так что идиома в порядке.
Ответ 2
Вы можете использовать
[x | [email protected](Goo _ _ _ _ _ _) <- foos]
Вы также можете определить
isGoo :: Foo -> Bool
isGoo (Goo _ _ _ _ _ _) = True
isGoo _ = False
а затем используйте filter
filter isGoo foos
или
[x | x <- foos, isGoo]