我一直在尝试使以下代码工作:
{-# 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)
请帮忙。
答案 0 :(得分:4)
在模式(a:b:xs)
中,您只匹配长度为> = 2的列表。您错过了单项列表的模式。
例如,这些匹配(a:b:xs)
:
"AWUBBWUBC"
- a
绑定到"A"
,b
绑定到"W"
,xs
绑定到"UBBWUBC"
('U':'B':'B':'W':'U':'B':'C':[]
)的语法糖。"AWU"
- a
和b
受到上述约束,但xs
现已绑定到"W"
。"AW"
- a
和b
再次分别与"A"
和"W"
绑定。像"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
我个人认为这是更优雅的,因为在这里很明显你的目标是与第二种模式相匹配(你不必编写一系列条件)。此外,人们几乎可以在语法上看到该函数处理所有可能的输入。