Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extract terms of specific data constructor from a list in Haskell

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?

like image 838
finnsson Avatar asked May 08 '10 16:05

finnsson


2 Answers

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.

like image 91
Don Stewart Avatar answered Oct 09 '22 15:10

Don Stewart


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]
like image 21
kennytm Avatar answered Oct 09 '22 17:10

kennytm