1

我想知道这个代码片段背后的模式匹配概念:

 split :: String -> Char -> [String]
 split [] delim = [""]
 split (c:cs) delim
     | c == delim = "" : rest
     | otherwise = (c : head rest) : tail rest
       where
         rest = split cs delim

我知道head返回列表的第一个元素并tail返回其余元素。但我仍然无法理解它的功能。这需要一个字符串并将其分解为给定字符的字符串列表。

4

1 回答 1

3

也许下面的形式更清楚:

split [] delim = [""]    -- a list containing only an empty String
split (c:cs) delim = let (firstWord:moreWords) = split cs delim
                     in if c == delim
                           then "" : firstWord : moreWords
                           else (c:firstWord) : moreWords

该函数遍历输入字符串,将每个字符与分隔符进行比较。如果当前字符不是分隔符,则将其附加在第一个单词(可能为空)的前面,这是由于拆分字符串的其余部分而产生的,如果是分隔符,则在前面添加一个空字符串余数分割的结果。

例如,split "abc cde" ' '收益的评估像

split "abc cde" ' '
    ~> 'a' == ' ' ? No, next guard
    ~> ('a' : something) : somethingElse

在哪里somethingsomethingElse稍后将通过拆分剩余"bc cde". After looking at the first character, it's been determined that whatever the final result is, its first entry starts with的“a”来确定。继续确定其余部分,

split "bc cde" ' '
    ~> ('b' : something1) : somethingElse1
       where (something1 : somethingElse1) = split "c cde" ' '

所以现在结果的第一个条目的前两个字符是已知的。然后从下一步确定以something1开头'c'。然后最后我们到达一个分隔符,即结果的第一个元素是在不参考以后的递归调用的情况下确定的,只有结果的其余部分在递归中被发现。

制定算法的另一种方法是(感谢@dave4420 的建议)

split input delim = foldr combine [""] input
  where
    combine c rest@(~(wd : wds))
        | c == delim = "" : rest
        | otherwise  = (c : wd) : wds
于 2012-02-06T10:30:03.547 回答