Aslan986
Aslan986

Reputation: 10324

How to correctly define a function like "any"

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:

enter image description here

If helpful i'm using ghci

Upvotes: 4

Views: 243

Answers (3)

Landei
Landei

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

epsilonhalbe
epsilonhalbe

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

sepp2k
sepp2k

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

Related Questions