English 中文(简体)
为什么GHC抱怨非无穷无尽的模式?
原标题:Why is GHC complaining about non-exhaustive patterns?
  • 时间:2012-05-22 09:44:50
  •  标签:
  • haskell
  • ghc

当我用GHC(使用 < code>-Wall 旗)编集下列代码时:

module Main where

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)

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
    | x > a = Node a left (insert x right)

main :: IO()
main = do
    let nums = [1..10]::[Int]
    print . foldr insert EmptyTree $ nums

GHC抱怨说, Infement 中匹配的图案并非详尽无遗:

test.hs|6| 1:
||     Warning: Pattern match(es) are non-exhaustive
||              In an equation for `insert : Patterns not matched: _ (Node _ _ _)

GHC为何发出这一警告? 很明显, GHC 抱怨的模式在 < code> Indig x (左键右键) 中处理。

最佳回答

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 的情况 。

我们可以写成这样:

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 位数 -- -- 即使比较出错! -- -- 我们最多只能做一次比较 。

问题回答

这是因为图案匹配不完整。 不能保证 xsuble a , x<>a , 或 x>a 中有一个是 NaN。 例如, 如果类型是 Double , 那么其中没有一个是 True

GHC is not able to infer whether your three guards in the insert x (Node a left right) cover all possible cases, and consequently there will be no body to be associated with insert x (Node a left right). Try replacing the last condition x > a with otherwise (a synonim for True). In this specific case however, it s true that the guards do not cover all cases, see augustss example about double numbers.





相关问题
Euler Problem in Haskell -- Can Someone Spot My Error

I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...

How does foldr work?

Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Problem detecting cyclic numbers in Haskell

I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...

Ways to get the middle of a list in Haskell?

I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...

haskell grouping problem

group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...

Closest equivalent to subprocess.communicate in Haskell

I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?