たぶん、次の形式でより明確になります。
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
とは、残りの 'a'`somethingElse
を分割することによって後で決定されます。"bc cde". After looking at the first character, it's been determined that whatever the final result is, its first entry starts with
残りを決定し続けると、
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 rest@(~(wd : wds))
| c == delim = "" : rest
| otherwise = (c : wd) : wds