Meda
Meda

Reputation: 2946

Accessing fields in tuples

I'm teaching myself Haskell, and while it was a most enlightening experience so far, I find some things that are easily done in C family of languages still a mystery. So, here is my very basic problem. I want a function to extract the tuples with a certain field equal to a given value. So far I have this code

withJob :: [(String, String, String)] -> String -> [String]
withJob [] _ = []
withJob ((_,_,x):xs) job
| job == x = x:(withJob xs job)
| otherwise = (withJob xs job)

users :: [(String, String, String)]
users = [("Jack", "22", "Programmer"), ("Mary", "21", "Designer"), ("John", "24", "Designer")]

When called like this users 'withJob' "Programmer" it outputs ["Programmer"] but I would like it to output [("Jack", "22", "Programmer")], however I don't know how to access the tuples and not the job(x) in job == x = x:(withJob xs job)

Upvotes: 4

Views: 232

Answers (2)

Will Ness
Will Ness

Reputation: 71119

Use @-patterns for that:

withJob :: [(String, String, String)] -> String -> [(String, String, String)]
withJob [] _   = []
withJob (t@(_,_,x):xs) job
   | job == x  = t : withJob xs job
   | otherwise =     withJob xs job

Upvotes: 8

MtnViewMark
MtnViewMark

Reputation: 5150

To expand what @Ingo was getting at: It would be more idiomatic Haskell to write:

jobField :: (String, String, String) -> String
jobField (_, _, j) = j

withJob :: [(String, String, String)] -> String -> [(String, String, String)]
withJob xs job = filter (\x -> jobField x == job) xs

We might go further:

data Person = Person { pName :: String, pAge :: Int, pJob :: String }

filterbyJob :: String -> [Person] -> [Person]
filterbyJob job xs = filter (\p -> pJob p == job) xs

And even then:

filterbyJob :: String -> [Person] -> [Person]
filterbyJob job = filter (\p -> pJob p == job)

Or even:

filterbyJob :: String -> [Person] -> [Person]
filterbyJob job = filter ((== job) . pJob)

At this point, unless one is going to use filterByJob an awful lot, it probably provides no real value beyond just writing the filter ((== job) . pJob) where you need it!

The point of this exercise is that there is a powerful function filter that one can just make use of, rather than rewriting that pattern of code each time. Not only does it save you time and code, but by reusing a known function, you make the code easier to understand by future programmers (including your future self!)

Upvotes: 4

Related Questions