Haskell实现二叉树insert函数报非穷尽模式匹配警告问题
不完整模式警告触发原因
GHC的-Wincomplete-patterns检查是纯语法层面的静态分析,不会对类型类方法的运算逻辑做语义层面的推导:
- 原代码里的两个守卫
x <= v和x > v,调用的是Ord类型类的自定义方法,检查器不会默认这两个条件对所有合法Ord实例满足二者必居其一、覆盖全部取值的逻辑。 - 对静态检查器而言,两个独立的类型类方法调用组成的守卫,天然存在两个条件都不命中的可能性,因此会判定
Branch分支的模式匹配没有覆盖所有情况,把所有Branch构造器的可能形态都列为未匹配模式。 otherwise是Haskell内置的恒真守卫(定义为otherwise = True),检查器可以直接识别到它会兜底所有前面守卫未命中的场景,因此替换后警告会直接消除。
补充说明
Haskell本身不强制Ord实例必须满足全序约束,开发者完全可以写出不符合x <= v和x > v互斥全覆盖的非法Ord实例,这种场景下原写法会直接抛出匹配失败的运行时错误,因此这个警告不算严格意义上的误报——检查器只是无法证明你使用的Ord实例符合常规的全序约定而已。
另外原代码中insert函数的Eq a约束是多余的,Ord a本身就隐含了Eq a约束,可以直接删除。
无警告的标准写法如下:
data Tree a = Leaf | Branch (Tree a) a (Tree a) deriving (Show, Eq) insert :: Ord a => a -> Tree a -> Tree a insert x Leaf = Branch Leaf x Leaf insert x (Branch l v r) | x <= v = Branch (insert x l) v r | otherwise = Branch l v (insert x r)
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

