我看到至少截至2018年9月,GHCI does not allow you to disable a warning locally(虽然你可以在整个文件中)。
但也许有其他方法让GHCI知道每个案件实际上都在处理中?
我有时使用的一个习惯是编写一个函数,其中第一个定义测试一些谓词并返回Left,其他定义考虑操作实际上有意义的参数。每当我这样做,我得到一个“模式匹配是非穷尽的”错误,但我真的在检查每个条件。
(对于激发这个玩具示例的真实世界代码,请参阅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
,所以它不适合Percussive
或Pitched
类型。
我会反驳哪个功能是“明确的”。即使乐器是倾斜的,你仍然必须分配一些最高音调,而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"
考虑到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,那么它将默默地产生应该不存在的音高。
实际上,正如上面评论中所指出的,还有第三种方式:使用PatternSynonyms
和COMPLETE
编译指示来说服GHC使警告无声。然而,这是更先进的。虽然它肯定有用于设计库,但对于这种特殊情况,它可能有点矫枉过正。