Haskell函数功能解析及非穷尽模式异常修复请求
解释Haskell筛法代码&修复非穷尽模式异常
嘿,我来帮你拆解这段代码的功能和问题:
代码功能解析
你写的这段代码:
a (b : bs) = b : [c | c <- (a bs), c `rem` b /= 0]
确实是埃拉托斯特尼筛法的递归实现思路,你的推测完全正确:
- 当输入非空列表
b : bs时,它把第一个元素b当作当前找到的质数保留下来; - 然后递归处理剩下的列表
bs,过滤掉其中所有能被b整除的元素(也就是筛掉b的倍数); - 最后把保留的
b和过滤后的递归结果拼接起来,逐步得到所有质数。
举个例子,如果输入是[2,3,4,5,6,7,8,9,10],它会先保留2,筛掉后续列表里的偶数得到[2,3,5,7,9],接着递归处理[3,5,7,9],保留3并筛掉9,最终得到标准质数列表[2,3,5,7]。
异常原因分析
你遇到的Non-exhaustive patterns in function a错误,核心原因是函数a只定义了非空列表的匹配模式,完全没处理空列表的情况。
当递归执行到最后一步时,比如你调用a [3,5..42],递归到末尾会触发a []的调用,但你的代码里没有对应的逻辑,Haskell不知道该怎么处理,就抛出了这个异常。
修复方案
只需要给a添加空列表的模式匹配即可——因为当输入是空列表时,筛法没有元素可处理,直接返回空列表就行:
a [] = [] -- 新增空列表的匹配模式 a (b : bs) = b : [c | c <- (a bs), c `rem` b /= 0]
现在再调用a [3,5..42],就会返回完整的质数列表:
Prelude> a [3,5..42] [3,5,7,11,13,17,19,23,29,31,37,41]
额外注意点
这个筛法有个前提:输入列表的第一个元素必须是质数,且后续元素是递增的大于它的数。如果输入包含合数(比如[4,5..10]),它会错误地把4当作质数,筛掉8后返回[4,5,7,9],结果就不符合预期了。所以使用时要保证输入是从质数开始的递增序列哦~
内容的提问来源于stack exchange,提问作者Netherar
相关产品推荐
相关产品推荐

