Riccardo是对的,GHC没有推断你的警卫不可能全都是假的。所以请接受他的回答。
我要去跳跃和谈论 编码风格。
您不使用 其它
的动机可能是它看起来不明智 :
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right)
| x == a = Node a left right
| x < a = Node a (insert x left) right
| otherwise = Node a left (insert x right)
阅读此代码时, 读者必须亲自确认, 最后卫兵会接受 < code>x & gt; a code > 的情况 。
我们可以写成这样:
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right) = case x `compare` a of
EQ -> Node a left right
LT -> Node a (insert x left) right
GT -> Node a left (insert x right)
ordering
type by compare
返回的 compare
中只有三个值 E/code>, LT
和 GT
,因此GHC可以确认您覆盖了所有可能性,而人类读者可以很容易地看到您正确覆盖了这些可能性。
这也是一种更有效率的代码:我们称 compare
一次,而不是拨,然后可能又拨 。
现在我还要再去谈一些懒惰的事
您可能也写了类似此函数的函数 :
contains :: (Ord a) => a -> Tree a -> Bool
contains _ EmptyTree = False
contains x (Node a left right) = case x `compare` a of
EQ -> True
...
当x =
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
但是现在回顾一下我对上面 插入
的定义。 当它给定的树是 Node
时, 它总是返回第一个参数总是 node
的 < code> 。 但是它没有在前面说明这一点: 它评估了 x`compare` a
。
我们可以重写 插入
,以进行尽可能晚的比较:
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right) = Node a newLeft newRight
where comparison = x `compare` a
newLeft = if comparison == LT then insert x left else left
newRight = if comparison == GT then insert x right else right
现在,我们尽快返回 node a
位数 -- -- 即使比较出错! -- -- 我们最多只能做一次比较 。