Liquid Haskell二叉搜索树删除实现的类型不匹配错误及修复
Liquid Haskell BST 删除功能类型不匹配错误分析与修复
我正在学习Liquid Haskell,实现二叉搜索树(BST)的删除功能时遇到了Liquid类型不匹配错误,代码和错误信息如下:
实现代码
data BST a = Leaf | Node { root :: a , left :: BST a , right :: BST a } {-@ data BST a = Leaf | Node { root :: a , left :: BSTL a root , right :: BSTR a root } @-} {-@ type BSTL a X = BST {v:a | v < X} @-} {-@ type BSTR a X = BST {v:a | X < v} @-} one :: a -> BST a one x = Node x Leaf Leaf add :: (Ord a) => a -> BST a -> BST a add k' Leaf = one k' add k' t@(Node k l r) | k' < k = Node k (add k' l) r | k < k' = Node k l (add k' r) | otherwise = t -- My BST deletion implementation del :: (Ord a) => a -> BST a -> BST a del _ (Node _ Leaf Leaf) = Leaf del _ Leaf = Leaf del x (Node k l r) | x < k = Node k (del x l) r | x > k = Node k l (del x r) | otherwise = case r of Leaf -> l _ -> Node k' l r' where k' = minKey r r' = del k' r where {-@ minKey :: {v:BST a | v /= Leaf} -> a @-} minKey (Node key Leaf _) = key minKey (Node _ l _) = minKey l
错误信息
Liquid Type Mismatch . Liquid Type Mismatch . . The inferred type VV : a VV : a . is not a subtype of the required type VV : {VV : a | k'##a1Jp9 < VV} . in the context k'##a1Jp9 : {VV : a | $VV##6040##k_ /= $ds_d1JQM##k_ && $VV##6040##k_ /= $ds_d1JRr##k_ && $VV##6040##k_ > $ds_d1JQM##k_ && $VV##6040##k_ > $ds_d1JRr##k_ && $VV##6040##k_ >= $ds_d1JQM##k_ && $VV##6040##k_ >= $ds_d1JRr##k_ && $ds_d1JQM##k_ < $VV##6040##k_ && $ds_d1JRr##k_ < $VV##6040##k_ && Demo.Example.root $ds_d1JQN##k_ < $VV##6040##k_ && Demo.Example.root $lq_anf$##7205759403793208731##d1JZF##k_ < $VV##6040##k_
错误原因
- 核心问题是
minKey函数的类型约束不够精确:原注解仅声明输入非空,但没有明确返回值是该BST中的最小元素。 - 当构造新节点
Node k' l r'时,Liquid Haskell需要验证r'符合BSTR a k'的约束(即r'中所有元素都大于k'),但由于minKey的类型信息不足,Liquid无法推断出del k' r后的r'满足这一条件,因此抛出类型不匹配错误。
修复方案
需要给minKey添加精确的Liquid类型注解,明确其返回值是输入BST的最小元素,同时可以给del函数补充类型约束辅助验证:
1. 完善minKey的类型约束
添加谓词定义和精确的类型签名,让Liquid能识别minKey的返回值是树中的最小值:
{-@ minKey :: {t:BST a | t /= Leaf} -> {v:a | isMin t v} @-} {-@ predicate isMin T V = V ∈ T && (∀ X ∈ T. V ≤ X) @-}
2. 给del函数添加BST合法性约束
确保删除操作后返回的仍然是合法BST:
{-@ del :: Ord a => a -> t:BST a -> {v:BST a | isBST v} @-} {-@ predicate isBST T = (T == Leaf) || (isBST (left T) && isBST (right T) && all (< root T) (left T) && all (> root T) (right T)) @-}
3. 修复后的完整代码
data BST a = Leaf | Node { root :: a , left :: BST a , right :: BST a } {-@ data BST a = Leaf | Node { root :: a , left :: BSTL a root , right :: BSTR a root } @-} {-@ type BSTL a X = BST {v:a | v < X} @-} {-@ type BSTR a X = BST {v:a | X < v} @-} one :: a -> BST a one x = Node x Leaf Leaf add :: (Ord a) => a -> BST a -> BST a add k' Leaf = one k' add k' t@(Node k l r) | k' < k = Node k (add k' l) r | k < k' = Node k l (add k' r) | otherwise = t {-@ del :: Ord a => a -> t:BST a -> {v:BST a | isBST v} @-} del :: (Ord a) => a -> BST a -> BST a del _ Leaf = Leaf del x (Node k l r) | x < k = Node k (del x l) r | x > k = Node k l (del x r) | otherwise = case r of Leaf -> l _ -> Node k' l r' where k' = minKey r r' = del k' r where {-@ minKey :: {t:BST a | t /= Leaf} -> {v:a | isMin t v} @-} {-@ predicate isMin T V = V ∈ T && (∀ X ∈ T. V ≤ X) @-} minKey (Node key Leaf _) = key minKey (Node _ l _) = minKey l {-@ predicate isBST T = (T == Leaf) || (isBST (left T) && isBST (right T) && all (< root T) (left T) && all (> root T) (right T)) @-} {-@ all :: (a -> Bool) -> BST a -> Bool @-} all _ Leaf = True all p (Node k l r) = p k && all p l && all p r
内容的提问来源于stack exchange,提问作者Minh Le
相关产品推荐
相关产品推荐

