たぶんそれは次のような形ではっきりしています:
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"を分割して後で決定します。最初の文字を見ると、最終結果が何であれ、最初のエントリは
'a'で始まります。残りを決定するために進むと、
split "bc cde" ' '
~> ('b' : something1) : somethingElse1
where (something1 : somethingElse1) = split "c cde" ' '
したがって、結果の最初のエントリの最初の2文字が分かりました。次のステップから something1
が 'c'
で始まると判断されます。最後に、デリミタに到達します。これは、結果の最初の要素が後の再帰呼び出しを参照せずに決定され、残った結果のみが再帰で見つかるままである場合です。
アルゴリズムを定式化するもう一つの方法は、(おかげさまで@ dave4420の提案です)
split input delim = foldr combine [""] input
where
combine c [email protected](~(wd : wds))
| c == delim = "" : rest
| otherwise = (c : wd) : wds