Haskell筛选列表出现次数≥x次元素的代码报错原因求解
报错原因分析
- 最核心的错误来自
output ++ x这行代码:Haskell中++是列表拼接运算符,要求左右两个操作数都为列表类型,你这里x是列表元素,不是列表,导致编译器错误认为你的输入列表元素应该是列表类型。你输入的[1,2,3...]里的数字字面量1属于Num类型类,编译器找不到「列表类型实现Num类型类」的实例,就抛出了第三个报错No instance for (Num [a1]) arising from the literal ‘1’。 - 前两个「类型变量歧义」报错都是上述类型错误的连锁反应:因为函数内部出现类型矛盾,编译器无法正常推断
moreThan函数的输入输出类型,既无法确定元素类型满足Eq约束,也无法确定返回值类型满足Show约束,就抛出了前两个报错。
代码其他问题说明
除了上述类型错误外,你的代码还存在多处逻辑和语法错误:
- 不必要的
do关键字:do仅用于编写Monad上下文的代码,你写的是纯列表处理函数,加do只会干扰类型推断,完全不需要。 - 边界条件失效:你给
moreThan2只写了(x:xs)的参数匹配,x:xs永远不可能为空,你写的null (x:xs)守卫永远不会触发,空列表的情况需要单独做参数匹配。 - 输出逻辑错误:你定义的
output是固定空列表,就算你把output ++ x改成正确的[x],也没法累加结果,正确写法是把满足条件的元素追加到递归调用返回的结果前。 - 判断条件缺失:你只判断了
suma < a和suma > a的情况,漏掉了suma == a的分支,等于阈值的元素也应该纳入结果。
修正后的可运行代码
import Data.List moreThan :: Eq a => Int -> [a] -> [a] moreThan _ [] = [] moreThan a (x:xs) = moreThan2 a (x:xs) where moreThan2 _ [] = [] moreThan2 a all@(x:xs) = let count = length $ filter (==x) all rest = filter (/=x) all in if count >= a then x : moreThan2 a rest else moreThan2 a rest main = print $ moreThan 2 [1,2,3,3,4,2,3,5,1,2] -- 运行输出:[1,2,3]
内容的提问来源于stack exchange,提问作者Raikiri13
相关产品推荐
相关产品推荐

