Haskell模式不匹配[_]

时间:2017-06-11 20:49:21

标签: string list haskell pattern-matching

我一直在尝试使以下代码工作:

{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
import Data.List
format :: String -> String
format [] = []
format (a:b:xs)
 | a == 'W' && b == 'U' = " " ++ format (drop 1 xs) 
 | otherwise = a : format (b:xs)

songDecoder :: String -> String
songDecoder xs = unwords. words . format $ xs

当我测试时:

  

songDecoder“AWUBBWUBC”

我希望“ABC”作为输出。但是,我得到了一个不寻常的模式匹配警告:

Pattern match(es) are non-exhaustive
In an equation for ‘format’: Patterns not matched: [_]

我不知道为什么我需要匹配[_]才能

format (a:b:xs)

请帮忙。

2 个答案:

答案 0 :(得分:4)

在模式(a:b:xs)中,您只匹配长度为> = 2的列表。您错过了单项列表的模式。

例如,这些匹配(a:b:xs)

  1. "AWUBBWUBC" - a绑定到"A"b绑定到"W"xs绑定到"UBBWUBC"'U':'B':'B':'W':'U':'B':'C':[])的语法糖。
  2. "AWU" - ab受到上述约束,但xs现已绑定到"W"
  3. "AW" - ab再次分别与"A""W"绑定。
  4. "A"这样的东西不会因为你可以将a绑定到"A"xs到空列表,但你没有任何东西b

    我希望这可以解释它!

答案 1 :(得分:4)

就像@EricFulmer在他的回答中写道一样,(a:b:xs)将列表与两个或更多项匹配。所以你的功能如下:

format [] = ...       -- empty list
format (a:b:xs) = ... -- two or more

Haskell警告说,一个元素[_]的列表与这些行中的任何一行都不匹配:两种模式都会失败。

因此,您应该添加一个子句,以指定在列表包含一个元素的情况下应该发生的情况,例如(可能):

format a@[_] = a

其中@别名运算符,它与只包含一个元素的列表绑定。

完整后我们获得:

format :: String -> String
format [] = []
format a@[_] = a
format (a:b:xs)
 | a == 'W' && b == 'U' = " " ++ format (drop 1 xs) 
 | otherwise = a : format (b:xs)

通过将比较移动到模式匹配中,我们可以使功能更优雅:

format :: String -> String
format [] = []
format a@[_] = a
format ('W':'U':xs) = format $ drop 1 xs 
format (a:b:xs) = a : format (b:xs)

现在最后一个案例可以简化为:

format (a:xs) = a : format xs

现在第二个子句(我们的format a@[_])已经过时,因为最后一个子句也处理了这个案例。所以我们将函数转换为:

format :: String -> String
format [] = []
format ('W':'U':xs) = format $ drop 1 xs 
format (a:xs) = a : format xs

我个人认为这是更优雅的,因为在这里很明显你的目标是与第二种模式相匹配(你不必编写一系列条件)。此外,人们几乎可以在语法上看到该函数处理所有可能的输入。