0
votes

Hey so I was learning Haskell in class and I was given the problem of removing all instances of something from a list. This is my go at it but I run into this error that I'm not sure I follow.

--delete element from list 
removeElement :: [a] -> [a]
removeElement x [] = []
removeElement x aList =
    if (head aList) == x
        then removeElement x (tail aList)
        else aList

The error I receive is this:

Couldn't match expected type `[[a]] -> [[a]]'
                with actual type `[a]'
    Relevant bindings include
      removeElement :: [a] -> [a] (bound at hwmk3.hs:8:1)
    The equation(s) for `removeElement' have two arguments,
    but its type `[a] -> [a]' has only one

I'm guessing that the syntax is wrong but I'm not sure how to fix it. Thanks for your help.

3
The signature says your function has one argument, and the equation says it has two. Mind you, this can have sense in Haskell, just probably not what you need here.n. 1.8e9-where's-my-share m.

3 Answers

5
votes

A few things:

Your type annotation indicates that your function will receive a single list parameter and return a list, whereas the implementation indicates that you should receive two parameters, the first of which is a single element.

Furthermore, since you are using == to compare, you'll need to make sure your type is of the Eq typeclass.

Your type annotation should probably look like this:

removeElement :: Eq a => a -> [a] -> [a]

You can also simplify things by taking advantage of pattern matching. You don't need to use head and tail if you define your function like this:

removeElement x aList@(y:ys) =
  if y == x
    then removeElement x ys
    else aList

However, there is a logic error in your conditional statement. Since this sounds like homework, I'll leave it to you to find the answer. Hint, try removeElement 3 [1, 2, 3]

1
votes

If you had omitted the explicit type declaration of your function, Haskell would have inferred something like a -> [a] -> [a]. In fact, it still infers that, which is why it is complaining that it does not agree with your stated type.

The problem reported by Haskell is this. Looking at your second equation, which desugars to

removeElement x = \aList -> if (head aList) == x then removeElement x (tail aList) else aList

a few things are "obvious":

  1. x :: [a] as the argument to removeElement.
  2. The lambda expression has type t -> v for some types t and v.

But we've already said that removeElement :: [a] -> [a], so can we come up with values for t and v such that [a] ~ t -> v? Maybe. Let's keep inferring types.

t is the type of aList, which we can infer from head aList == x to be [[a]]. Skipping the recursive call for now, we can also see that aList is the return value, so v is also [[a]]. Thus, t -> v is really [[a]] -> [[a]].

Can we match a value of type [[a]] -> [[a]] with [a]?

No, which is why you get the exact error message you do.

0
votes

Your type signature should be

removeElement :: a -> [a] -> [a]

Also, it looks like your function does not do what you think it will do.