atmosfir
atmosfir

Reputation: 13

Haskell too many arguments error

I am learning Haskell. I am trying to make a function that deletes integers out of a list when met with the parameters of a certain function f.

deleteif :: [Int] -> (Int -> Bool) -> [Int]
deleteif x f = if x == [] 
                then [] 
                else if head x == f 
                       then deleteif((tail x) f)  
                       else [head x] ++ deleteif((tail x) f)

I get the following errors :

Upvotes: 0

Views: 1265

Answers (3)

leftaroundabout
leftaroundabout

Reputation: 120711

As already said, deleteif((tail x) f) is parsed as deleteif (tail x f), which means tail is applied to the two arguments x and f, and the result would then be passed on as the single argument to deleteif. What you want is deleteif (tail x) f, which is equivalent to (deleteif (tail x)) f and what most languages1 would write deleteif(tail x, f).

This parsing order may seem confusing initially, but it turns out to be really useful in practice. The general name for the technique is Currying.

  • For one thing, it allows you to write dense statements without needing many parentheses – in fact deleteif (tail x f) could also be written deleteif $ tail x f.
  • More importantly, because the arguments don't need to be “encased” in a single tuple, you don't need to supply them all at once but automatically get partial application when you apply to only one argument. For instance, you could use this function like that: deleteif (>4) [1,3,7,5,2,9,7] to yield [7,5,9,7]. This works by partially applying the function2 > to 4, leaving a single-argument function which can be used to filter the list.

1Indeed, this style is possible in Haskell as well: just write the signatures of such multi-argument functions as deleteif :: ([Int], Int->Bool) -> [Int]. Or write uncurry deleteif (tail x, f). But it's definitely better you get used to the curried style!

2Actually, > is an infix which behaves a bit different – you can partially apply it to either side, i.e. you can also write deleteif (4>) [1,3,7,5,2,9,7] to get [1,3,2].

Upvotes: 2

No_signal
No_signal

Reputation: 402

the problem is in deleteif((tail x) f)

it becomes deleteif (tail x f)

so tail gets 2 arguments

and then deleteif a

so deleteif gets 1 argument

you want deleteif (tail x) f

head x == f is wrong you want `f (head x)

you can use pattern matching ,guards and make it more generic

deleteif :: [a] -> (a -> Bool) -> [a]
deleteif [] _ = []
deleteif (x:xs) f
    | f x       =     deleteif xs f 
    | otherwise = x : deleteif xs f

Upvotes: 2

Louis Wasserman
Louis Wasserman

Reputation: 198103

The issue is that you don't use parentheses to call a function in Haskell. So you just need to use

if f (head x)
   then deleteif (tail x) f
   else [head x] ++ deleteif (tail x) f 

Upvotes: 4

Related Questions