I'm writing a program that takes in a list of elements (such list must take both integers and fractional numbers) and gives a list of cut sums:
My result so far is:
cuttingSum :: Num a => [a] -> [a]
cuttingSum l =
let
cuttingSum_iter [] res = reverse (res)
cuttingSum_iter ll res =
cuttingSum_iter (tail ll) ((foldl (+) 0 ll) :: res)
in
cuttingSum_iter l []
main = do
print $ cuttingSum [1,2,3]
I'm getting error:
ERROR "task9-02-1.hs":5 - Inferred type is not general enough
*** Expression : foldl (+) 0 ll
*** Expected type : a
*** Inferred type : _26
I'm using Hugs as it's the task requirement, but ghci also shows some sort of similar error. What's the problem?
The problem is simply a typo, you have foldl (+) 0 ll :: res
instead of foldl (+) 0 ll : res
, with only one :
. This is because ::
indicates the type of an expression. When you have
cuttingSum_iter ll res = cuttingSum (tail ll) ((foldl (+) 0 ll) :: res)
This is equivalent to
cuttingSum_iter ll res = cuttingSum (tail ll) ((foldl (+) 0 ll) :: b)
Because res
as an argument and res
as a type live in different namespaces. In the type namespace, any identifier beginning with a lower case letter is a type variable, and as we know the name of a variable doesn't matter to the compiler, only to the programmer. From this point, I'll refer to it as b
to avoid confusion with the res
argument.
Since you're telling the compiler that the expression foldl (+) 0 ll
has the type b
, it fails the type checking stage. The compiler can figure out that ll
is at least a list, and using it in foldl (+) 0
means that it must contain Num
elements, so foldl (+) 0 ll
must have type Num a => a
. This does not match with the type b
, since b
does not have the Num
constraint. This is what leads to the error message you see of
ERROR "task9-02-1.hs":5 - Inferred type is not general enough
The inferred type is not general enough because the inferred type has the Num
constraint.
In GHC, you'd instead get the error
Couldn't match type ‘t’ with ‘res’
because type variable ‘res’ would escape its scope
This (rigid, skolem) type variable is bound by
an expression type signature: res
at <interactive>:13:57-79
Expected type: [res]
Actual type: [t]
Relevant bindings include
ll :: [t] (bound at <interactive>:13:21)
cuttingSum_iter :: [t] -> [a] -> [a] (bound at <interactive>:12:5)
In the third argument of ‘foldl’, namely ‘ll’
In the second argument of ‘cuttingSum_iter’, namely
‘((foldl (+) 0 ll) :: res)’
To me, this one is a little more clear since it mentions the "type variable res
" on the second line, and says it expected it to have [res]
while expecting the type [t]
where cuttingSum_iter
has the type [t] -> [a] -> [a]
. Seeing that it mentions "type variable res
" and "Expected type: [res]
", this at least points a little more towards what the problem was, although it still isn't immediately clear what is actually the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With