Reputation: 10324
Studying Haskell, i'm trying to code a function takeIf
that given a condition and a list returns all the list's element that satisfies the condition.
Examples of desired output:
takeIf (>0) [] --> []
takeIf (>0) [-1, 0, 1, 2] --> [1,2]
I tried this definition:
takeIf cond [] = []
takeIf cond (x:xs) = if (cond x)
then x:(takeIf cond xs)
else []:(takeIf cond xs)
but it doesn't work.
My first question is: I have
:t takeIf --> ([a] -> Bool) -> [[a]] -> [[a]]
why? Why not:
:t takeIf --> (a -> Bool) -> [a] -> [a]
How can I get this code to work?
This is the error I get:
If helpful i'm using ghci
Upvotes: 4
Views: 243
Reputation: 54584
An altenative are folds, e.g.
filter' f = foldr go [] where
go x xs = if f x then x:xs else xs
Upvotes: 0
Reputation: 15959
since sepp2k was faster than me - I just want to add that you might want to have a look at filter
and it's source which is exactly the function you try to reimplement.
Here is the actual source
filter :: (a -> Bool) -> [a] -> [a]
filter _pred [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xs
Upvotes: 3
Reputation: 370212
[]:(takeIf cond xs)
Here you're trying to prepend [] as the new first element to the result of takeIf cond xs
. Since []
is a list, GHC infers from that that the result of takeIf cond xs
must be a list of lists. Since the result of takeIf has the same type as its argument, that means xs
must also be a list of lists. And since x
is an element of xs
, x
must consequently be a list.
It seems like you intended []:
to mean "prepend nothing to the list", but []
isn't nothing, it's the empty list. [] : []
, doesn't give you []
, it gives you [[]]
. Likewise [] : [1,2,3]
would give you [[], 1, 2, 3]
- except that that's not well-typed, so what it really gives you is a type error.
If you want to prepend nothing to a list, just don't prepend anything to the list, i.e. just use someList
instead of [] : someList
.
Upvotes: 10