避免在GHCI中出现不适当的非详尽模式匹配警告

问题描述 投票:1回答:2

Before you dismiss this as a duplicate

我看到至少截至2018年9月,GHCI does not allow you to disable a warning locally(虽然你可以在整个文件中)。

但也许有其他方法让GHCI知道每个案件实际上都在处理中?

The Question

我有时使用的一个习惯是编写一个函数,其中第一个定义测试一些谓词并返回Left,其他定义考虑操作实际上有意义的参数。每当我这样做,我得到一个“模式匹配是非穷尽的”错误,但我真的在检查每个条件。

Example

(对于激发这个玩具示例的真实世界代码,请参阅pExprToHExpr here的定义。)

这段代码:

{-# LANGUAGE ViewPatterns #-}

data Cowbell = Cowbell
  deriving Show
data Instrument = Rattle
                | Drums (Maybe Cowbell)
                | Violin
                | Oboe
  deriving Show

pitched :: Instrument -> Bool
pitched Rattle                 = False
pitched (Drums Nothing)        = False
pitched (Drums (Just Cowbell)) = True
pitched Violin                 = True
pitched Oboe                   = True

highestPitch :: Instrument -> Either String Float
highestPitch i@(pitched -> False) =
  Left $ "Instrument " ++ show i ++ " has no pitch."
highestPitch (Drums (Just Cowbell)) = Right 800
highestPitch Violin                 = Right 5000
highestPitch Oboe                   = Right 2000

生成此错误:

example.hs:19:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘highestPitch’:
        Patterns not matched:
            Rattle
            (Drums Nothing)

在其他条件下,我只是细分Instrument类型:

data Percussive = Rattle | Drums
data Pitched    = Violin | Oboe
data Instrument = Percussive Percussive
                | Pitched Pitched

但是(在这个假想的物理学中)一组Drums可能具有最高音高,如果它包括Cowbell,所以它不适合PercussivePitched类型。

haskell pattern-matching warnings suppress-warnings non-exhaustive-patterns
2个回答
4
投票

我会反驳哪个功能是“明确的”。即使乐器是倾斜的,你仍然必须分配一些最高音调,而highestPitch提供你需要知道的一切,如果乐器是否倾斜。从而

-- An instrument with a highest pitch is pitched; the others aren't.
pitched :: Instrument -> Bool
pitched = either (const False) (const True) . highestPitch


highestPitch :: Instrument -> Either String Float
highestPitch (Drums (Just Cowbell)) = Right 800
highestPitch Violin                 = Right 5000
highestPitch Oboe                   = Right 2000
highestPitch Rattle = Left "Instrument Rattle has no pitch"
highestPitch (Drums Nothing) = Left "Instrument Drums Nothing has no pitch"

2
投票

考虑到pitched的定义,GHC不检查详尽性。因此,检查器基本上忽略了第一个等式,从而引发警告。

实际上,从计算科学的角度来看,GHC无法在一般情况下决定,因为存在视图模式的详尽性是不可判定的。充其量,GHC可能会使用一些复杂的静态分析,但它只是选择完全忽略pitched

为了使警告静音,我可以看到两个主要选项。第一种是在最后添加一个捕获所有案例。

highestPitch :: Instrument -> Either String Float
highestPitch i@(pitched -> False) =
  Left $ "Instrument " ++ show i ++ " has no pitch."
highestPitch (Drums (Just Cowbell)) = Right 800
highestPitch Violin                 = Right 5000
highestPitch Oboe                   = Right 2000
highestPitch i                      =
  Left $ "Instrument " ++ show i ++ " has no pitch."
  -- we could even use "error", in certain cases

如果我们遵循这条路线,在这种特定情况下我们可以删除第一个等式。

highestPitch :: Instrument -> Either String Float
highestPitch (Drums (Just Cowbell)) = Right 800
highestPitch Violin                 = Right 5000
highestPitch Oboe                   = Right 2000
highestPitch i                      =
  Left $ "Instrument " ++ show i ++ " has no pitch."

或者,我们可以使最后一个案例Oboe成为一个全能的案例:

highestPitch :: Instrument -> Either String Float
highestPitch i@(pitched -> False) =
  Left $ "Instrument " ++ show i ++ " has no pitch."
highestPitch (Drums (Just Cowbell)) = Right 800
highestPitch Violin                 = Right 5000
highestPitch _oboe                  = Right 2000   -- must be an Oboe

不过,我不是这种方法的忠实粉丝,因为如果pitched包含一个bug,那么它将默默地产生应该不存在的音高。

实际上,正如上面评论中所指出的,还有第三种方式:使用PatternSynonymsCOMPLETE编译指示来说服GHC使警告无声。然而,这是更先进的。虽然它肯定有用于设计库,但对于这种特殊情况,它可能有点矫枉过正。

© www.soinside.com 2019 - 2024. All rights reserved.