避免在GHCI中避免使用不当的非排量模式匹配警告



在将其视为重复之前

之前

我看到,至少从2018年9月开始,GHCI不允许您在本地禁用警告(尽管您可以在整个文件中)。

,但也许还有其他方法可以让GHCI知道每种情况实际上都在处理?

问题

我有时会使用一个习语是写一个函数,其中第一个定义(S)测试了一些谓词和返回,而其他定义则考虑操作实际上有意义的参数。每当我这样做时,我都会得到"模式匹配(ES)是非详尽的"错误,但是我确实在检查每个条件。

示例

(对于激励这个玩具示例的现实世界代码,请参见pExprToHExpr的定义。)

此代码:

{-# 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类型。

i会逆转哪个函数为"确定性"。即使音调仪器,您仍然必须分配一些最高的音高,而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"

GHC未考虑pitched的定义。因此,Checker基本上忽略了第一个方程式,从而引起了警告。

的确,从计算科学的角度来看,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包含一个错误,这将默默产生应该不存在的音调。

实际上,正如上面在评论中指出的那样,有第三种方法:使用PatternSynonymsCOMPLETE Pragma说服GHC使警告保持沉默。但是,这更为先进。虽然它绝对具有设计库的用途,但对于这种特定情况,它可能有点过分。

相关内容

  • 没有找到相关文章

最新更新