Phillip
Phillip

Reputation: 87

ERROR - Cannot infer instance

I am a beginner in Haskell. I have this function

test f xs 
  | length xs == 0  = []
  | f (head xs)     = head xs : test f (tail xs)
  | otherwise       = test f (tail xs)

This function should make a list from every element of the list xs which is matching the f value but it gives back an error:

test 1 [1,2]
ERROR - Cannot infer instance
*** Instance   : Num (a -> Bool)
*** Expression : test 1 [1,2]

This part:

| f (head xs)

should be a Bool but is it? Is it working as a filter? How can I make this function work? Thanks in advance.

Upvotes: 1

Views: 1750

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

Always use type signatures

Evidently, f is a kind of predicate: you apply it to values in the list, and it yields a boolean value. So the type of test is

test :: (a -> Bool) -> [a] -> [a]

BTW the standard name for this is filter.

If you're not sure about the signature yourself, you can actually ask GHCi

> :t test
test :: (a -> Bool) -> [a] -> [a]

...but I strongly recommend to instead start with the signature: first think about what you want your function to accomplish, then worry about the implementation.

Anyway, so to test the test function, you need to give it an (a -> Bool) function and a list. Is 1 a function? I daresay not, therefore test 1 [1,2] can't make sense. You probably mean something like test (\x -> x==1) [1,2], which can also be written simply test (==1) [1,2].

A couple of remarks on your code:

  • You're using guards to check if a list is empty. First of all, to just check if a list is empty, never evaluate its length – this needs to traverse the entire list. You could use the null function, which does just that – check if a container is empty ...
  • ... but that still leaves the problem of actually taking a value out of the list. You can indeed take the first value of a nonempty list with head, but this is only safe in a branch where you've first checked that it's nonempty. This is easy to get wrong. A much better solution is to just pattern match on the list head: instead of

    test f xs 
      | length xs == 0  = []
      | f (head xs)     = ...
    

    write

    test f [] = []
    test f (x:xs)
      | f x   = ...
    

    This way, you can't mistakenly evaluate the head of an empty list, because the compiler ensures that x is only in scope in a clause that has been checked to be nonempty.

Look at the source code of the standard filter function for final reference.


Actually, 1 can be a function... number literals are overloaded in Haskell; you could theoretically write

instance Num (Integer -> Bool) where
  fromInteger n x = x == n

and then you can define f = 1 :: Integer -> Bool, and use it for test too. But... this would be a really bad idea; such instances make for very confusing code.

Upvotes: 5

Related Questions