模式匹配列表失败

时间:2019-06-22 13:48:12

标签: string list haskell

我有以下代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Wow</h1>
<h2>Blablablub</h2>
<p>Lorem Ipsum...</p>
<h1>Lalalala</h1>
<p>Lorem Ipsum...</p>
<h1>Ble</h1>
<h2>Test</h2>
<h3>Third</h3>
<p>Lorem Ipsum...</p>

编译后应该返回给我一个在非转义空格处分割的字符串列表。

但是发生以下情况:

{-
Returns a list of Strings splitted by ' '. '\\ ' is kept as ' '
-}
splitOnWhitespace :: String -> [String]
splitOnWhitespace s = concatOnBackslash $ splitOn " " s

{-
concats Strings on '\\' with a whitespace
-}
270 concatOnBackslash :: [String] -> [String]
271 concatOnBackslash [] = []
273 concatOnBackslash [x] = [x]
274 concatOnBackslash [x, xs] = case last x of
275     '\\' -> [(init x) ++ " " ++ xs]
276     _ -> [x, xs]
277 concatBackslash (x : xx : xs) = case last x of
278     '\\' -> concatOnBackslash (((init x) ++ " " ++ xx) : xs)
279     _ -> x: concatOnBackslash (xx : xs)

我在这里做什么错了?

1 个答案:

答案 0 :(得分:3)

这确实是正确的。第一个问题是您的最后一个子句定义了一个函数concatBackslash,而其他子句定义了一个函数concatOnBackslash(带有On)。因此,这意味着Haskell考虑了这两个不同函数。您可以将它们重命名为:

concatOnBackslash :: [String] -> [String]
concatOnBackslash [] = []
concatOnBackslash [x] = [x]
concatOnBackslash [x, xs] = case last x of
    '\\' -> [(init x) ++ " " ++ xs]
    _ -> [x, xs]
concatOnBackslash (x : xx : xs) = case last x of
    '\\' -> concatOnBackslash (((init x) ++ " " ++ xx) : xs)
    _ -> x: concatOnBackslash (xx : xs)

现在测试用例可以使用,但是功能仍然不是很安全。

last :: [a] -> a(和init :: [a] -> [a])功能非总计。对于空列表,这些操作将失败:

Prelude> last []
*** Exception: Prelude.last: empty list
Prelude> init []
*** Exception: Prelude.init: empty list

因此,这意味着concatOnBackslash会出错,因为第一个元素为空,例如:

Prelude Data.List.Split> concatOnBackslash ["", "a"]
*** Exception: Prelude.last: empty list

因此,您最好在此处使用模式匹配,例如:

concatOnBackslash :: [String] -> [String]
concatOnBackslash [] = []
concatOnBackslash [x] = [x]
concatOnBackslash [[], xs] = ...
concatOnBackslash [x@(_:_), xs] = case last x of
    '\\' -> [(init x) ++ " " ++ xs]
    _ -> [x, xs]
concatOnBackslash ([] : xx : xs) = ...
concatOnBackslash (x@(_:_) : xx : xs) = case last x of
    '\\' -> concatOnBackslash (((init x) ++ " " ++ xx) : xs)
    _ -> x: concatOnBackslash (xx : xs)