0
votes

When I try to run the following function, I get an error:

len' [] = 0
len' (_:xs) = 1 + len' xs

listlon [] = 0
listlon [[]] = 1
listlon (x:xs) = ((len' x):(listlon xs))

functions.hs:41:1: error: • Non type-variable argument in the constraint: Num [a] (Use FlexibleContexts to permit this) • When checking the inferred type listlon :: forall a t. (Num [a], Num a) => [[t]] -> [a]

Can some one explain me, How to fix this? What is this error conveying exactly?

1
Always use type signatures. They will make your intentions clear to the reader and yourself, and will help you understand the error messages.Lazersmoke

1 Answers

3
votes

The line

listlon [] = 0

produces the output 0 in place of something of type [a]. You most probably meant listlon [] = []. However I suggest listlon = map length or listlon = map len'. Or maybe I just do not understand what it is that you really want. As a first step, it always helps to provide the intended signature. Is it true that you are after a function listlon :: [[a]] -> [Int]?

If my understanding is correct, the most direct fix would be:

listlon [] = []
listlon [x] = [len' x]
listlon (x:xs) = len' x : listlon xs

This fixes the types. But you can notice that the second equation is redundant and this is sufficient

listlon [] = []
listlon (x:xs) = len' x : listlon xs

and now you can notice that this in fact is mapping len' over the list, hence map len' as the pointfree definition of listlon.

The error says that the compiler got confused about the return type. You are trying to return a Num by literals 0 and 1 as well as in form of a list (constructed by the last line). The constraint Num [a] is only possible using the extension FlexibleContexts. But in fact it only indicates the problem I described above. These kinds of error messages are sometimes confusing because the compiler cannot read your mind, and so it assumes you know what you are doing and only reports a problem when it cannot continue inferring types anymore due to some conflict.