Reputation: 12124
I have an algebraic data type called Person
looks like this:
data Person =
Person { firstName :: String
, lastName :: String
, height :: Float
, age :: Int
} deriving (Show, Eq)
I also have a list of Person
filled with various information about people, now say I want to return all the data of one specific Person
based on firstName
alone, how would I do that?
Like search through all the firstName
s stored in the list, and then returning either Just Person
if the query matches or Nothing
if there isn't any match
Upvotes: 2
Views: 193
Reputation: 54068
Very simply, you could write a custom lookup function:
lookupBy :: Eq b => (a -> b) -> [a] -> b -> Maybe a
lookupBy _ [] _ = Nothing
lookupBy f (x:xs) key = if f x == key then Just x else lookupBy f xs key
Then you could use it as
main = do
let people = [Person "John" "Doe" 68 30, Person "Jane" "Smith" 63 28]
print $ lookupBy firstName people "Jane"
print $ lookupBy lastName people "Doe"
print $ lookupBy age people 29
print $ lookupBy height people 63
This would print
Just (Person {firstName="Jane", lastName="Smith", height=63, age=28})
Just (Person {firstname="John", lastName="Doe", height=58, age=30})
Nothing
Just (Person {firstName="Jane", lastName="Smith", height=63, age=28})
(assuming that it compiles, I have not run this code but it should work).
If you want to choose on whether you get a single item or a list of matching items, you could do
import Data.Maybe (listToMaybe)
lookupAllBy :: Eq b => (a -> b) -> [a] -> b -> [a]
lookupAllBy f xs key = filter (\x -> f x == key) xs
lookupBy :: Eq b => (a -> b) -> [a] -> b -> Maybe a
lookupBy f xs key = listToMaybe $ lookupAllBy f xs key
Upvotes: 1
Reputation: 2382
You can use filter
to return a list that contains all the Person
with a given condition on firstName
.
For instance:
filter (\x -> firstName x == "John") xs
where xs
contains the list of Person
. This will return an empty list ([]
) if no Person
matches the criteria.
Upvotes: 4