Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing fields in tuples

Tags:

haskell

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)

like image 780
Meda Avatar asked Dec 15 '22 12:12

Meda


2 Answers

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
like image 123
Will Ness Avatar answered Dec 18 '22 01:12

Will Ness


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!)

like image 42
MtnViewMark Avatar answered Dec 18 '22 02:12

MtnViewMark