tags:

views:

87

answers:

2

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

foos = [Bar, Goo, Bar, Bar, Goo]

and wish to extract all Goos 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?

+3  A: 

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]
KennyTM
+11  A: 

Seems like there are two parts to this question:

  1. Is there an easier way to do pattern matching
  2. 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.

Don Stewart
But OP wants something similar to `[Just x | Just x <- ls]`, not `catMaybes` or `rights`.
KennyTM
That's fine, the question is in two parts: whether list comprehensions are ok, and secondly, what form of pattern matching. I'll clarify.
Don Stewart