模式匹配涵盖多个案例

Set*_*r22 2 haskell

我做了一个函数来比较字符串(当然这是我正在做的一个练习,以便学习,我很清楚<,>运算符在大多数现代语言中都使用字符串).为了做一些递归我正在使用模式匹配函数,但我不确定发生了什么.这是我的代码:

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  = '='
Run Code Online (Sandbox Code Playgroud)

因此,我的代码中有很多案例,例如一个空列表和一个单例列表,一个空列表和一个普通列表(多个元素).当然还有对称的对应物.我怎样才能确保检查它们?是否有什么东西在幕后?或者只是比较字符串(不是字符,这是我的意图)在某些时候,我不知道它?

  • 总而言之,我的问题是:我是否涵盖了我的代码可能出现的所有案例,如果不是这样,我怎么能确定?我将如何处理对称情况(如第一个列表为空,但第二个列表没有,反之亦然)而没有声明两个不同的模式.

bhe*_*ilr 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>
Run Code Online (Sandbox Code Playgroud)

请注意,在中间的两种情况下,我们不必指定具有数据的列表实际上具有数据,因为如果它传递了第一个模式,则两者都不为空.如果你有not (xs == [] && ys == []) && (xs == [] && ys == _)(这不是代码,不要尝试运行),那么ys不是[].我们也没有检查xs == [x] && ys == [y]因为[x] == x:[]哪个(z:zs)x == z和匹配的情况[] == zs.

为了确保您确实覆盖了所有模式,您应该-fwarn-non-exhaustive-patterns按照@StephenDiehl的建议启用.

  • @ Setzer22我也建议不要使用`'='`,`'''和`'>'`作为返回值,使用内置的`Ordering`数据类型:`data Ordering = LT | EQ | GT`,所以你要将你的类型签名改为`String - > String - > Ordering`并用'LT`替换''<'`,用'EQ`替换`'='`和``>'`` GT`.由于`Ordering`只能是这三个值中的一个,所以你不能搞砸了! (2认同)

Ste*_*ehl 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:
            [] _
            (_ : (_ : _)) []
            (_ : (_ : _)) (_ : _)
            [_] []
            ...
Run Code Online (Sandbox Code Playgroud)