Alex Smith
Alex Smith

Reputation: 51

Select in Haskell

I am trying to create a function in HASKELL that takes a predicate and two lists as arguments and returns a list composed of elements from the second list in those positions where the predicate, when applied to the element in the corresponding positions of the first list, returns True. What I have so far is...

select :: (t -> Bool) -> [t] -> [a] -> [a]
select _ [] = []  
select p (x:xs)   
    | p x       = x : select p xs  
    | otherwise = select p xs

p11tests = [select even [1..26] "abcdefghijklmnopqrstuvwxyz" == "bdfhjlnprtvxz", select (<= 'g') "abcdefghijklmnopqrstuvwxyz" [1..26] == [1,2,3,4,5,6,7]]

p11tests is where I test the function. Not sure what I am doing wrong.

Upvotes: 1

Views: 1138

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477318

You are not working with two lists. Your function is in essence a filter function where you retrieve all items x in the (first) list that satisfy the predicate p.

You want to check if the predicate matches for the item of the first list, and in that case yield the item in the second list, so:

select :: (t -> Bool) -> [t] -> [a] -> [a]
select _ [] [] = []
select _ (_:_) [] = []
select _ [] (_:_) = []
select p (x:xs) (y:ys)
    | p x = …
    | otherwise = …

where I leave filling in as an exercise.

You can also work with a combination of zip, filter and map where you first zip the two items together, then filter items where the first item of the 2-tuples satisifies the predicate, and then you map on the second element. So something like:

select :: (t -> Bool) -> [t] -> [a] -> [a]
select p xs = map snd . filter (p . fst) . zip xs

Upvotes: 1

Related Questions