非详尽模式匹配只是因为我离开了'otherwise =`?

时间:2017-09-22 00:12:55

标签: haskell pattern-matching ghc

我在Haskell中编写了一个简单的程序来播放the guessing game described in The Rust Programming Language book

  

以下是它的工作原理:程序将生成1到100之间的随机整数。然后它将提示玩家输入猜测。输入猜测后,它将指示猜测是太低还是太高。如果猜测正确,游戏将打印祝贺并退出。

这是我写的:

import Control.Monad (when)
import System.Random (randomRIO)

-- | Check if the guess is correct, otherwise provide a hint
respond :: Int -> Int -> String
respond correct guess
  | guess > correct = "Smaller than " ++ show guess
  | guess < correct = "Larger than " ++ show guess
  | guess == correct = "Correct! " ++ show correct

-- | Main game loop; prompt for input and repeat until guessed correctly
play :: Int -> IO ()
play x = do
  putStr "Guess: "
  guess <- read <$> getLine
  putStrLn $ respond x guess
  when (guess /= x) $ play x

-- | Start the game with a random number between 1 and 100
main :: IO ()
main = play =<< randomRIO (1, 100)

代码有效,但GHC向我发出"Pattern match(es) are non exhaustive. In an equation for 'respond': Patterns not matched: _ _"

的警告

我将这两个下划线表示为Ints函数的两个respond。我不明白的是我没有涉及哪种情况。那些不是Maybe Int或任何特殊的 - 函数需要两个有效的Ints,所以我只需要处理整数 - 我认为没有不能被视为大于,小于或等于另一个的数字?

这只是GHC假设我没有涵盖所有情况,因为我没有添加最终otherwise =后卫吗?即使它在逻辑上涵盖了所有情况。

另外,如果您有关于如何编写更多惯用Haskell的任何提示,我会很感激。我还在学习基础知识。

2 个答案:

答案 0 :(得分:7)

GHC根本不知道a > ba < ba == b中的一个必须评估为True。 (实际上,有可能编写一个违反此假设的Ord实例 - 尽管大多数程序员都不会考虑这样做,当然Int的实例在这方面表现得很好。)

您可以通过使用完整的模式匹配来明确GHC明确涵盖所有情况,例如

respond correct guess = case compare guess correct of
    GT -> ...
    LT -> ...
    EQ -> ...

GHC在防御otherwiseTrue的详尽检查中也有一个特例,因此您可以添加(或替换)其中一名守卫作为替代解决方案。

respond correct guess
    | guess > correct = ...
    | guess < correct = ...
    | otherwise = ...

答案 1 :(得分:3)

编译器只进行静态语义分析。这无法看到这三种情况涵盖了所有可能的输入,因为运算符的含义是在运行时确定的。

您的代码可以证明是正确的。如果您想避免GHC发出警告,可以将最终条件更改为otherwise