Список соответствия шаблонов не работает - PullRequest
0 голосов
/ 22 июня 2019

У меня есть следующий код:

{-
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)

, который компилирует и должен возвращать мне список строк, разбитых на неперекрытый пробел.

Однако происходит следующее:

*Filesystem> splitOnWhitespace "a1"
["a1"]
*Filesystem> splitOnWhitespace "a1 a2"
["a1","a2"]
*Filesystem> splitOnWhitespace "a1 a2 a3"
*** Exception: src/Filesystem.hs:(271,1)-(275,24): Non-exhaustive patterns in function concatOnBackslash

*Filesystem> splitOnWhitespace "a1 a2 a3 a4"
*** Exception: src/Filesystem.hs:(271,1)-(275,24): Non-exhaustive patterns in function concatOnBackslash

Что я здесь не так делаю?

1 Ответ

3 голосов
/ 22 июня 2019

Это действительно правильно. Первая проблема состоит в том, что ваше последнее предложение определяет функцию concatBackslash, тогда как другие предложения определяют функцию concat<b>On</b>BackslashOn). Таким образом, это означает, что Haskell считает эти две разные функции. Вы можете переименовать их в:

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

Теперь контрольный пример будет работать, но функция все еще не очень безопасна.

Функции last :: [a] -> ainit :: [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 [<b>[]</b>, xs] = ...
concatOnBackslash [x<b>@(_:_)</b>, xs] = case last x of
    '\\' -> [(init x) ++ " " ++ xs]
    _ -> [x, xs]
concatOnBackslash (<b>[]</b> : xx : xs) = ...
concatOnBackslash (x<b>@(_:_)</b> : xx : xs) = case last x of
    '\\' -> concatOnBackslash (((init x) ++ " " ++ xx) : xs)
    _ -> x: concatOnBackslash (xx : xs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...