我正在编写一个程序,它接受一个元素列表(这样的列表必须同时包含整数和小数)并给出 cut 总和的列表:
到目前为止我的结果是:
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]
我收到错误:
ERROR "task9-02-1.hs":5 - Inferred type is not general enough
*** Expression : foldl (+) 0 ll
*** Expected type : a
*** Inferred type : _26
我正在使用Hugs,因为它是任务要求,但ghci也显示出某种类似的错误。有什么问题?
答案 0 :(得分:11)
问题只是一个错字,你有foldl (+) 0 ll :: res
而不是foldl (+) 0 ll : res
,只有一个:
。这是因为::
表示表达式的类型。当你有
cuttingSum_iter ll res = cuttingSum (tail ll) ((foldl (+) 0 ll) :: res)
这相当于
cuttingSum_iter ll res = cuttingSum (tail ll) ((foldl (+) 0 ll) :: b)
因为res
作为参数而res
作为一种类型存在于不同的名称空间中。在类型命名空间中,任何以小写字母开头的标识符都是类型变量,并且我们知道变量的名称对编译器无关紧要,只对程序员有意义。 从这一点开始,我会将其称为b
,以避免与res
参数混淆。
由于您告诉编译器表达式foldl (+) 0 ll
具有类型b
,因此它未通过类型检查阶段。编译器可以确定ll
至少是一个列表,并且在foldl (+) 0
中使用它意味着它必须包含Num
个元素,因此foldl (+) 0 ll
必须具有类型{{1 }}。这与类型Num a => a
不匹配,因为b
没有b
约束。这就是导致您看到
Num
推断类型不够通用,因为推断类型具有ERROR "task9-02-1.hs":5 - Inferred type is not general enough
约束。
在GHC中,你会得到错误
Num
对我来说,这个更清晰一点,因为它在第二行提到了“类型变量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)’
”,并表示它期望res
同时期望类型{{1其中[res]
的类型为[t]
。看到它提到“类型变量cuttingSum_iter
”和“预期类型:[t] -> [a] -> [a]
”,这至少指出了问题的原因,尽管仍然不能立即明确实际是什么问题