A common problem I got in Haskell is to extract all terms in a list belonging to a specific data constructor and I'm wondering if there are any better ways than the way I'm doing it at the moment.
Let's say you got
data Foo = Bar | Goo
, the list
开发者_StackOverflowfoos = [Bar, Goo, Bar, Bar, Goo]
and wish to extract all Goo
s from foos
. At the moment I usually do something like
goos = [Goo | Goo <- foos]
and all is well. The problem is when Goo
got a bunch of fields and I'm forced to write something like
goos = [Goo a b c d e f | Goo a b c d e f <- foos]
which is far from ideal. How you do usually handle this problem?
Seems like there are two parts to this question:
- Is there an easier way to do pattern matching
- Are list comprehensions ok here?
Firstly, there is a better way to match on fields you don't care about:
goos = [ x | x@(Goo {}) <- foos]
Secondly, using list comprehensions is a perfectly cromulent way of writing these kinds of filters. For example, in the base library, catMaybes is defined as:
catMaybes :: [Maybe a] -> [a]
catMaybes ls = [x | Just x <- ls]
(from the base library). So that idiom is fine.
You could use
[x | x@(Goo _ _ _ _ _ _) <- foos]
You could also define a
isGoo :: Foo -> Bool
isGoo (Goo _ _ _ _ _ _) = True
isGoo _ = False
and then use filter
filter isGoo foos
or
[x | x <- foos, isGoo]
精彩评论