Может быть, это понятнее в следующей форме:
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
где something
и somethingElse
будут определены позже путем разделения остатка "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
person
Daniel Fischer
schedule
06.02.2012