我做了一个比较字符串的功能(当然这是我为了学习而做的练习,我很清楚&lt ;,>操作符都适用于大多数现代字符串语言)。为了做一些递归,我使用模式匹配功能,但我不确定发生了什么。这是我的代码:
compareStrings :: String -> String -> Char
compareStrings (x:xs) (y:ys)
| x > y = '>'
| x < y = '<'
| x == y = compareStrings xs ys
compareStrings [a] [b]
| a < b = '<'
| a > b = '>'
| a == b = '='
因此,我的代码中有很多情况,例如一个空列表和一个单例列表,一个空列表和一个普通列表(多个元素)。当然还有对称的对应物。我怎样才能确保检查它们?是否有什么东西在引擎盖下或者只是比较字符串(不是字符,这是我的意图)在某些时候,我不知道它?
答案 0 :(得分:6)
对于这样的问题,你只关心每个列表的第一个元素,如果列表是空的。通常,您只需确定您的函数正在运行的列表的哪些元素,然后处理案例,直到您涵盖了可以传入的任何类型的列表。
对于此实例,您希望在两个列表都包含数据(x:xs)
和(y:ys)
时以及当其中一个或两个都为空时进行处理。你可以用
-- Both are empty
compareStrings [] [] = '='
-- The first is empty, the second is not
compareStrings [] ys = '<'
-- The first is not empty, the second is
compareStrings xs [] = '>'
-- Both have data
compareStrings (x:xs) (y:ys) = <your current implementation>
请注意,在中间的两种情况下,我们不必指定包含数据的列表实际上具有数据,因为如果它传递了第一个模式,则两者都不为空。如果您有not (xs == [] && ys == []) && (xs == [] && ys == _)
(这不是代码,请勿尝试运行),则ys
不是[]
。我们也不必检查xs == [x] && ys == [y]
的情况,因为[x] == x:[]
将(z:zs)
与x == z
和[] == zs
匹配。
为了确保您确实覆盖了所有模式,您应该按照@StephenDiehl的建议启用-fwarn-non-exhaustive-patterns
。
答案 1 :(得分:5)
我是否涵盖了我的代码可能出现的所有情况,如果情况并非如此,我怎么能确定?
事实上,这种模式匹配并非详尽无遗,对于某些输入,它并未定义。您可以告诉GHC使用标记-fwarn-non-exhaustive-patterns
向您发出警告,并打印出您未覆盖的案例。
cover.hs:2:1: Warning:
Pattern match(es) are non-exhaustive
In an equation for `compareStrings':
Patterns not matched:
[] _
(_ : (_ : _)) []
(_ : (_ : _)) (_ : _)
[_] []
...